Describes the relationship between handler and logoff.

Source: Internet
Author: User
Tags call back

I have been reading the usage of handler and logoff in Android over the past few days. However, I have already understood the usage of handler and logoff in the past, but today I am going to have a deep understanding of the source code of the two. Sure enough, there are so many articles in it that I have learned a lot and it is imperative to write a blog record immediately... (It seems that more source code will be available in the future ~~~ ·).

Before the example starts, let's take a look at Google API's explanation of the two:

Let's take a look at the logoff class:

Let's take a look at the explanation provided by Google for the handler class:

To put it simply, you can understand that there is a message queue.MessageQueue(You Should Know About The Queue .....), What handler needs to do is to transfer a message object to this message queue and process the message from the message queue, who is responsible for traversing and Retrieving messages in the message queue to handler? Yes, the traversal and retrieval work is done by logoff. Okay. Let's take a look at the example I wrote below (if there are any great gods, don't be surprised .. Don't be surprised ...)

Let's take a look at the construction of the entire project:

The layout file main. xml contains a textview and a button for a long time. (Believe it or not ..... I won't show it to you either)

Now let's take a look at the code in the activity.

Public class hlactivity extends activity {/** called when the activity is first created. */private textview = NULL; private button BTN = NULL; // Private handler = NULL; public static int I = 0; @ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); initralweight ();/* Handler = new handler () {@ override public void handlemessage (Message MSG) {// todo auto-generated method stub textview. settext ("the number of currently clicked running threads is" + MSG. arg1) ;}}; */} private class btnlistener implements onclicklistener {@ overridepublic void onclick (view v) {// todo auto-generated method stubtestthread TT = new testthread (); thread t = new thread (TT); T. start () ;}} private class testthread implements runnable {private handler = NULL; @ overridepublic void run () {// todo auto-generated method stublooper. prepare (); handler = new handler () {@ overridepublic void handlemessage (Message MSG) {// todo auto-generated method stubsystem. out. println ("the current number is:" + MSG. arg1) ;}}; while (I <10) {message MSG = new message (); MSG. arg1 = I ++; handler. sendmessage (MSG);} logoff. loop () ;}} private void initralweight () {textview = (textview) findviewbyid (R. id. text); BTN = (button) findviewbyid (R. id. BTN); BTN. setonclicklistener (New btnlistener ());}}

The function is very simple. When you click the button, the thread is enabled, and the thread will continuously I ++, generate a message object, and ship it to the message queue. Then

Handler = new handler () {@ override public void handlemessage (Message MSG) {// todo auto-generated method stub system. out. println ("the current number is:" + MSG. arg1 );}};

This part of the code is responsible for processing the messages obtained from the message queue, so someone asked here,

Looper.prepare();
Looper.loop();

What is the purpose?

Also, where is the message queue? Why didn't I see it?

Don't worry. Let's take a look at the source code of Logoff:

Public class logoff {// The logoff object in each thread is actually a threadlocal, that is, the local thread storage (TLS) object Private Static final threadlocal sthreadlocal = new threadlocal (); // The final messagequeue mqueue of the message queue in logoff; // The current thread mthread ;//... Other attributes // each logoff object contains its message queue, and its own thread private logoff () {mqueue = new messagequeue (); mrun = true; mthread = thread. currentthread () ;}// we call this method to create the logoff object public static final void prepare () {If (sthreadlocal. get ()! = NULL) {// an attempt to create a logoff in a logoff thread will throw an exception throw new runtimeexception ("only one logoff may be created per Thread");} sthreadlocal. set (New logoff ();} // other methods}

Here we can see that the logoff constructor logoff () is declared as private. That is to say, we cannot directly use the logoff constructor externally, how can we create a logoff object?

Public static final void prepare () {If (sthreadlocal. Get ()! = NULL) {// an attempt to create a logoff in a logoff thread will throw an exception throw new runtimeexception ("only one logoff may be created per Thread");} sthreadlocal. set (New logoff ());}

The prepare () function provides us with the function of initializing logoff objects. If we don't know what threadlocal is, let's take a look at my previous blog, which is about threadlocal, well, I will not talk about it here ..., this function requires us to pay attention to what information it gives us. Obviously, it tells me that as long as you call this method, the system will add a logoff object in threadlocal, and a thread can only have one logoff. If there is more than one, an exception is thrown ......

Well, the following is the focus:

Public static final void loop () {Looper me = mylooper (); // get the current thread Looper messagequeue queue = me. mqueue; // get the MQ of the current logoff. clearcallingidentity (); Final long ident = binder. clearcallingidentity (); // starts the loop while (true) {message MSG = queue. next (); // retrieve the message if (MSG! = NULL) {If (msg.tar get = NULL) {// if no target is the end signal, exit the loop return;} // log... If (Me. mlogging! = NULL) me. mlogging. println (">>>>> dispatching to" + msg.tar get + "" + MSG. callback + ":" + MSG. what); // very important! Assign the real processing work to the target of the message, that is, the handler msg.tar get. dispatchmessage (MSG); // or log... If (Me. mlogging! = NULL) me. mlogging. println ("<finished to" + msg.tar get + "" + MSG. callback); // not understood below, also does not affect understanding final long newident = binder. clearcallingidentity (); If (ident! = Newident) {log. WTF ("logoff", "thread identity changed from 0x" + long. tohexstring (ident) + "to 0x" + long. tohexstring (newident) + "while dispatching to" + msg.tar get. getclass (). getname () + "" + MSG. callback + "What =" + MSG. what);} // reclaim message resource MSG. recycle ();}}}

After we call the logoff. Loop () method, logoff actually starts to work.

Looperme = mylooper(); // get the current thread loopermessagequeue queue = me. mqueue; // get the MQ of the current Looper

Obtain the messagequeue of the current logint. Each logint has a message queue, which serves as a member attribute of logint.

Then, while loop through the message queue, constantly retrieve data.

Message MSG = queue. Next (); // retrieve the message

First determine whether the message queue is in the end...

if (msg != null)
If (msg.tar get = NULL) {// if the message does not have the target signal as the end signal, exit the loop return ;}

Then there is a series of printed logs:

// Log... If (Me. mlogging! = NULL) me. mlogging. println (">>>>> dispatching to" + msg.tar get + "" + msg. Callback + ":" + MSG. What );

Below is the core of this method.

msg.target.dispatchMessage(msg);

The actual function of this method is to pass the message to the handler class for processing, while handler uses

handleMessage

And process the information.

Some people have said

dispatchMessage

Is it a handler method? Don't worry.

Let's take a look at the internal implementation of the dispatchmessage method:

// Process the message. This method is called by logoff.
Public
Void dispatchmessage (Message MSG ){
If (msg. Callback
! = NULL ){
// If callback is set for the message, that is, the runnable message, process callback! Handlecallback (MSG );}
Else {
// If callback is set for handler, call back is executed.
If (mcallback
! = NULL ){
/* This method allows the activity to implement the handler. Callback interface, avoiding writing handler to override the handlemessage method. See http://alex-yang-xiansoftware-com.iteye.com/blog/850865
*/If (mcallback. handlemessage (MSG )){
Return ;}}
// If the message does not have callback, call handlemessage (MSG );}}

As you can see, there is such a code in the dispatchmessage method:

 handleMessage(msg);

Haha ~~~~~ I think everyone should understand the relationship between handler and logoff and the call ......

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.