Deep understanding of handler asynchronous communication mechanism in Android _android

Source: Internet
Author: User
Tags message queue prepare

First, the problem: After Android startup will create a main thread in the new process, also known as the UI thread (not thread-safe) This thread is mainly responsible for monitoring screen click events and interface drawing. When the application needs to carry out time-consuming operations such as network requests, such as direct in the main thread is prone to occur ANR errors. So you create a child thread to perform time-consuming tasks, and when the child thread finishes, you need to notify the UI thread and modify the interface, you can't modify the UI directly on the child thread.

Workaround: The message queue mechanism enables the communication of child and UI threads.

The mechanism includes handler, message Queue, and Looper. Handler can send a message/runnable object to Looper, which puts the message in the message queue of the owning thread, and Looper automatically broadcasts the message/runnable object in the message queue to the Chengri of the owning line handler. A message or Runnable object that is received by handler processing.

1, Handler

Each time the handler object is created, it is automatically bound to the thread that created it. If the main thread contains a message queue by default, you will need to create one to store it yourself.

Handler is a messenger that communicates with multiple threads. For example, create a ahandler in thread A, bind it to a alooper, and create a Message Queuing amessagequeue that belongs to a. Then send a message to Alooper,alooper using Ahandler in thread B to save the message to Amessagequeue and then broadcast Amessagequeue to Chengri of line a ahandler, which receives the message for processing. So that communication can be realized.

2. Message Queue

In the main thread the default contains a message queue that does not need to be created manually. In a child thread, the Looper.prepare () method is used to check whether a child thread already has a Looper object, and if so, it cannot be created because each thread can only have one message queue. If not, create a message queue for the child thread.

3, the complete creation handler mechanism
The handler class contains looper pointers and MessageQueue pointers, while Looper contains actual MessageQueue and current thread pointers.

The following explains the handler creation process for both the UI thread and the worker thread:

First, when the handler is created, the current thread is automatically checked for the Looper object, and if it is included, the message queue within the handler is pointed to a message queue inside the Looper, otherwise an exception request executes the Looper.prepare () method.

-In the UI thread, the system automatically creates the Looper object, so the mechanism can be used directly by a new handler;

-In a worker thread, if you create handler directly, you throw a Run-time exception-that is, by checking the ' thread-value ' mapping table, the current thread has no Looper object. So you need to call the Looper.prepare () method first. In the Prepare method, the Threadlocal<looper> object is used to create a looper for the current thread (using a values class, a map map, which stores value for thread only, A Looper object is stored here for the current thread. Then continue to create handler, let the message queue within handler point to the Looper message queue (This is important, let handler point to the message queue in Looper, that is, the two share the same message queue, and then handler send messages to this message queue, Looper get messages from this message queue). Then looper the loop message queue. When a message is fetched, the target in the messages object, that is, the original send handler, is invoked to callback the handler's Handlemessage () method for processing.

Handler mechanism

4, the core
-handler and Looper share message queues, so handler send messages as long as row, Looper directly to the message.

-Thread and Looper mapping table: A thread can map up to a Looper object. Check the table to see if the current thread contains looper and, if it is already contained, no longer create a new looper.

5, based on such a mechanism is how to achieve thread isolation, that is, in-line communication.

The core is that each thread has its own handler, message queue, Looper system. And the handler of each thread is public. b threads can invoke the handler of a thread to send a message to a shared message queue, and then A's looper will automatically fetch messages from the shared message queue for processing. The opposite is the same.

Child threads send messages to the main thread

Communication between child threads

Second, the above is based on the use of the main thread provided by the handler send messages out, and then the main thread of the Looper from the message queue to get and handle. Then there are two other things:

1, the main thread to send messages to the child thread;

The method used is similar to the previous. To instantiate the ahandler in a child thread and set a method to process the message, and because the child thread does not have Message Queuing and Looper polling, add Looper.prepare (), Looper.loop () to create the message queue, and to open the poll, respectively. Then use the Ahandler in the main thread to send the message.

2, the communication between child thread A and child thread B.


Three, handler inside have what practical API?
Please remember:

Handler is simply sending a message to a message queue (or using the Post method)
They have a more convenient way to help communicate with the UI thread.
If you look at the handler API now, you can see these methods clearly:

    • Post
    • Postdelayed
    • Postattime

code example

The code here is very basic, but you can take a good look at the annotations.

Example 1: Using the handler "post" method

The public class Testactivity extends activity {//. Standard stuff @Override public void onCreate (Bundle saved Instancestate) {///...//all standard stuff//we ' re creating a new handler I//And we ' re in the UI
 
  
Thread (default)//So this Handler is associated with the UI thread Handler mhandler = new Handler ();
  
I want to start doing something really long//which means I should run the fella in another thread. I do this by sending a message-in the form of another Runnable object//But-I ' m going to create a Runnab Le object or a message for this Runnable mrunnableonseparatethread = new Runnable () {@Override public void run
 
      
() {//Do some long operation Longoperation (); After Mrunnableonseparatethread are done with it's job,//I need to tell the user that I'm done//which means I need to send a message back to the UI thread//Who does we know that ' s associatEd with the UI thread?
          
Mhandler.post (New Runnable () {@Override public void run () {//Do some UI related thing
      Like update a progress bar or TextView//...}
 
 
    });
 
  
}
  }; Cool but I ' ve not executed the mrunnableonseparatethread yet//I ' ve only defined the "message to" sent/when
 
  I execute it though, I want it to is different thread//that is the whole point.
New Thread (Mrunnableonseparatethread). Start ();
 }
 
}

If there is no handler object at all, the callback post method can be tricky.

Example 2: Using the Postdelayed method

Recently this site introduced a new feature, every time I have to simulate the automatic completion of the EditText function, each text changes will trigger an API call, retrieve data from the server.

I wanted to reduce the number of app call APIs, so I decided to use the handler postdelayed method to implement this feature.

This example is not for parallel processing, only about handler sending messages to message queues and arranging messages to be executed at some point in the future.

//The below code is inside a Textwatcher//which implements the OnTextChanged method/
 
/I ' ve simplified it to only highlight the parts we ' RE//interested in private long Lastchange = 0; @Override public void ontextchanged (final charsequence chars, int start, int before, int count) {//T He handler are spawned from the UI thread new handler (). postdelayed (//argument 1 for postdelated = message T O is sent new Runnable () {@Override public void run () {if nochangeintext_inthelastfew 
Seconds ()) {Searchandpopulatelistview (chars.tostring ());
 
    Logic}},//argument 2 for postdelated = delay before execution 300);
Lastchange = System.currenttimemillis ();
Private Boolean nochangeintext_inthelastfewseconds () {return System.currenttimemillis ()-Lastchange >= 300} 

Finally I put the "Postattime" this method as a link to the reader, master handler it? If so, you can use the thread as much as you like.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.