Article transferred from: http://android.blog.51cto.com/268543/343823
1. Android Process
Before learning about the android thread, you must first understand the android process. When a program is started for the first time, Android starts a Linux Process and a main thread. By default, all components of the program will run in the process and thread. In addition, Android assigns a Linux User to each application. Android will try to keep a running process. When the memory resources are insufficient, Android will try to stop some processes and release enough resources for other new processes to use, it can also ensure that the current process being accessed by the user has enough resources to respond to the user's events in a timely manner. Android judges the importance of a process based on the component category and component Status in the process. Android first stops unimportant processes. There are five levels of importance from high to low:
- Foreground Process
The foreground process is the process currently in use by the user. Only some foreground processes can exist at any time. They are the last one ended, when the memory is low to the root of them can not run. In general, in this case, the device will perform memory scheduling and stop some foreground processes to maintain a response to user interaction.
- Visible Process
The visible process does not contain foreground components, but displays a visible process on the screen. It is very important, unless the foreground process needs to obtain its resources, it will not be aborted.
- Service Process
A service started using the startservice () method is running. This service is not of the two higher importance mentioned above. Although the process where the service is located is not directly visible to users, they execute tasks that users are very concerned about (such as playing MP3 and downloading data from the network ). As long as the foreground and visible processes have enough memory, the system will not recycle them.
- Background Process
An activity that is invisible to users is running (the onstop () method has been called ). these processes have no direct impact on the user experience. They can be recycled when the service process, visible process, and frontend process require memory. Generally, many invisible processes are running in the system. They are stored in the LRU (least recently used) list so that they can be recycled immediately when the memory is insufficient. If an activity executes its lifecycle, closing the process has no significant impact on user experience.
- Empty Process
No program components are running. The only reason for running these processes is to use them as a cache to shorten the restart time required by the next program. The system often terminates these processes, which can regulate the balance between the program cache and the system cache.
When Android rates the importance of processes, it selects the highest level. In addition, when another process is dependent, the level of a process may increase. A process serving other processes is never more important than the process being served. Because the service process is more important than the background activity process, it is best to start a service for a time-consuming activity to do this work, instead of starting a sub-process, this operation takes longer time than the activity. For example, playing music in the background and uploading images captured by cameras to the Internet. Using the service, processes can obtain at least the important level of the service process, you do not need to consider the current status of the activity. Broadcast
When receivers is time-consuming, it should also enable a service rather than opening a thread.
2. Single-threaded Model
When a program is started for the first time, Android starts a corresponding main thread at the same time. The main thread is mainly responsible for processing UI-related events, such as user key events, the user contacts screen events and Screen Drawing events, and distributes related events to corresponding components for processing. Therefore, the main thread is often called the UI thread. When developing Android applications, you must follow the single-thread model principle: Android UI operations are not thread-safe and must be executed in the UI thread.
2.1 The Sub-thread updates the UI
The android UI is single-threaded. To avoid dragging the GUI, some time-consuming objects should be handed over to independent threads for execution. If the background thread executes the UI object, Android sends an error message calledfromwrongthreadexception. When such an exception is thrown in the future, you must know what is going on!
2.2 Message Queue
In the single-thread model, Android designs a message queue to solve similar problems. The message queue can be used between threads to exchange information with handler and logoff components. They are described as follows:
1. Message message refers to the information exchanged between threads. When the background thread needs to update the UI for processing data, the message contains some data to the UI thread. 2. Handler handler is the main handler of the message, responsible for sending the message and executing the message content. The background thread uses the passed handler object reference to sendmessage ). When handler is used, the handlemessage (Message) method of the implement class is required. It is the operation content for processing these messages, such as update
UI. It is usually necessary to subclass handler to implement the handlemessage method. 3. Message Queue message queue, which is used to store messages published by handler and executed first-in-first-out. Each message queue has a corresponding handler. Handler sends a message to the message queue in two ways: sendmessage or post. Both messages are inserted at the end of the message queue and executed first-in-first-out. However, messages sent using the two methods are executed in a slightly different way: a message object is sent using sendmessage, which will be processed by the handlemessage () function of handler; the post method sends a runnable object, which is executed by itself. 4. logoff is the manager of the message queue in each thread. Android does not have a global message queue, while Android automatically creates a message queue for the main thread (ui thread), but no message queue is created in the Child thread. Therefore, the logoff value of the main thread obtained by calling logoff. getmainlogoff () is not null, but the logoff value of the current thread may be null by calling logoff. mylogoff.
The API Doc provides the correct method for using logoff for sub-threads:
Class looperthread extends thread {public handler mhander; Public viod run () {loler. prepare (); // create the Logoff of this thread and create a messagequeuemhandler = new handler () {public void handlemessage (Message MSG) {// process incoming message here}; logoff. loop (); // start logoff and listen to message queue }}
The general process of this message mechanism:
1. After the logoff. Loop () method starts running, the non-null message in the message queue is retrieved cyclically in the receiving order.
2. At the beginning, all messages in the message queue are null. When handler. sendmessage (Message) is sent to message queue, this function sets the target attribute of the message object to the current handler object. Then logoff retrieves the message, and calls the dispatchmessage function of the hander to which the target of the message points to process the message.
In the dispatchmessage method, the user determines how to process the message. The priority ranges from high to low:
1) callback in the message, an object that implements the runnable interface, where the run function is used for processing;
2) The mcallback in handler points to an object that implements the callback interface, which is processed by the handlemessage;
3) the classes corresponding to the handler object for processing messages inherit and implement the handlemessage function. The handlemessage function is used to process messages.
We can see that the handlemessage method we implemented has the lowest priority!
3. After handler processes the message (update UI), logoff sets the message to NULL for recycling!
There are many articles on the Internet about how the main thread interacts with other sub-threads, how information is transmitted, and who finally processes information, my personal understanding is the simplest method-this thread is used to determine which thread the logoff object in the handler object belongs! 1. if the parameter of the constructor of the handler object is null, It is the Logoff of the current thread; 2. logoff. getmainlogoff () is the logoff object of the main thread. mylogoff () obtains the logoff object of the current thread.
Let's take an example to simulate the process of retrieving data from the network and loading data to listview:
Public class listprogressdemo extends listactivity {private arrayadapter <string> adapter; private arraylist <string> data; Private Static final int progress_dialog = 1; Private Static final int state_finish = 1; private Static final int state_error =-1; @ overrideprotected void oncreate (bundle savedinstancestate) {// todo auto-generated method stubsuper. oncreate (savedinstancestate); setcontentview (R. layout. activity_main); (button) findviewbyid (R. id. load_handler )). setonclicklistener (new view. onclicklistener () {public void onclick (view v) {// todo auto-generated method stubdata = NULL; Data = new arraylist <string> (); adapter = NULL; showdialog (progress_dialog); New progressthread (handler, data ). start () ;}}) ;}@ overrideprotected dialog oncreatedialog (int id) {// todo auto-generated method stubswitch (ID) {Case progress_dialog: Return progressthread. show (this, "", "loading. please wait ...... ", true); default: return NULL;} private class progressthread extends thread {private handler; private arraylist <string> data; Public progressthread (handler, arraylist <string> data) {This. handler = handler; this. data = data ;}@ overridepublic void run () {// todo auto-generated method stubfor (INT I = 0; I <8; I ++) {data. add ("listitem"); // try {thread for background data processing. sleep (100);} catch (interruptedexception e) {message MSG = handler. obtainmessage (); bundle B = new bundle (); B. putint ("State", state_error); MSG. setdata (B); handler. sendmessage (MSG) ;}} message MSG = handler. obtainmessage (); bundle B = new bundle (); B. putint ("State", state_finish); MSG. setdata (B); handler. sendmessage (MSG) ;}// you do not even need to set looperhere, because handler uses the looperprivate final handler = new handler (looper. getmainlooper () {public void handlemessage (Message MSG) {int state = MSG. getdata (). getint ("state"); Switch (state) {Case state_finish: dismissdialog (progress_dialog); toast. maketext (getapplicationcontext (), "loaded", toast. length_long ). show (); adapter = new arrayadapter <string> (getapplicationcontext (), android. r. layout. simple_list_item_1, data); setlistadapter (adapter); break; default: Break ;}}};}
Android also provides a tool class: asynctask. It makes the use of the UI thread very simple. It makes it easier to create long-running tasks that need to interact with the user interface, without the need to use threads and handler.
1) subclass asynctask 2) implement the following methods defined in asynctask onpreexecute () to prepare for execution; doinbackground (Params ...) start to execute background processing. You can call publishprogress to update the real-time task progress. onprogressupdate (Progress ...) after the publishprogress method is called, the UI thread calls this method to display the progress of the task on the interface, for example, through a progress bar. Onpostexecute (result) after the operation is completed, the result is sent to the UI thread. None of the four methods can be called manually. Besides doinbackground (Params ...) the other three methods are called by the UI thread, so the requirements are as follows: 1) The asynctask instance must be created in the UI thread; 2) the asynctask.exe cute method must be called in the UI thread. Note that the task can only be executed once. Otherwise, exceptions may occur during multiple calls. In addition, you cannot manually stop it. Pay attention to this to see if it meets your needs! During usage, it is found that the parameter settings of the asynctask constructor must be clear: asynctask <Params, progress, result> Params corresponds to the parameter type of doinbackground (Params. New asynctask(cmd.exe cute (Params... params), that is, the incoming Params data. You can execute (data) to transmit one data, or execute (data1, data2, data3) data. Progress corresponds to the parameter type of onprogressupdate (Progress...); Result corresponds to the parameter type of onpostexecute (result.