Message processing for Android

Source: Internet
Author: User

It's a work record ...

First of all, the update of the interface in Android must be done in the middle of the main thread, and when we want to update the interface in the sub-thread, we can handle it through the two classes of handler and message. For example, a new thread has been opened for downloading tasks, displaying progress bars through handler, and so on. The approximate process is that you first get a message and then call SendMessage to send it, and then you can do it in the overridden function of the handler class.

New Thread () {            publicvoid                 Run () {... = Message.obtain ();                ...                 = Network_error



}.start ();
Private New Handler () {        publicvoid  handlemessage (android.os.Message msg) {              Switch  (msg.what) {            case  network_error:                 ...  Break ;            }        };    };

We can click to see the source code of handler and message, we will find that there will be two classes, Looper and MessageQueue in the interior.

Look at the message first,

 Public Final classMessageImplementsparcelable { Public intwhat ;  Public intarg1;  Public intarg2;  PublicObject obj;  PublicMessenger ReplyTo; /* Package*/ intflags; /* Package*/ LongWhen ; /* Package*/Bundle data; /* Package*/Handler Target; /* Package*/Runnable callback; /* Package*/Message Next; ...}

Then the first question is, why not direct message msg = new Message (), but instead use Message.obtain (); This is explained in the comments:

    /*** Return A new Message instance from the global pool.     Allows us to * avoid allocating new objects in many cases. */     Public StaticMessage obtain () {synchronized(spoolsync) {if(SPool! =NULL) {Message m=SPool; SPool=M.next; M.next=NULL; Spoolsize--; returnm; }        }        return NewMessage (); } Public StaticMessage Obtain (Handler H, Runnable callback); Public StaticMessage obtain (Handler H,intwhat)
...

A thread-pool-like approach is used to extract messages from the global pool, and when all the messages in the global pool are exhausted, the new message () avoids the performance losses associated with frequent application and release of resources. This class also writes a number of overloaded methods with different parameters. Another way to get a message is handler.obtainmessage (), see the source can know is also called message.obtain ();

Then is the way to send the message, Handler.sendmessage:

 Public void Sendtotarget () {    target.sendmessage (this);}

The target here can be seen above, which is a member of the handler type of message that represents the handler object that receives the message. The SendMessage method inside the handler class can be seen along the way, and the last step is to invoke the Mqueue method enqueuemessage the MessageQueue class member object of the handler class.

    Public Final BooleansendMessage (Message msg) {returnsendmessagedelayed (MSG, 0); }          Public Final BooleanSendmessagedelayed (Message msg,LongDelaymillis) {        if(Delaymillis < 0) {Delaymillis= 0; }        returnSendmessageattime (MSG, systemclock.uptimemillis () +Delaymillis); }     Public BooleanSendmessageattime (Message msg,LongUptimemillis) {MessageQueue Queue=Mqueue; if(Queue = =NULL) {runtimeexception e=NewRuntimeException ( This+ "Sendmessageattime () called with no Mqueue"); LOG.W ("Looper", E.getmessage (), E); return false; }        returnenqueuemessage (Queue, MSG, uptimemillis); }    Private BooleanEnqueuemessage (MessageQueue queue, Message msg,LongUptimemillis) {Msg.target= This; if(masynchronous) {msg.setasynchronous (true); }        returnqueue.enqueuemessage (msg, uptimemillis); }

So SendMessage, in fact, is sent to the MessageQueue queue of the handler member of the Message object. And then the question is, how did the message come out? First look at the handler class:

 Public classHandler {FinalMessageQueue Mqueue; FinalLooper Mlooper; FinalCallback Mcallback; Final Booleanmasynchronous;        IMessenger Mmessenger; /*** Default Constructor Associates This handler with the {@linkLooper} for the * current thread. * * IF This thread does not has a looper, this handler won ' t being able to receive messages * So an exception is THR     Own. */     PublicHandler () { This(NULL,false); }           PublicHandler (Callback Callback,Booleanasync) {... mlooper=Looper.mylooper (); if(Mlooper = =NULL) {            Throw NewRuntimeException ("Can ' t create handler inside thread that have not called looper.prepare ()"); } mqueue=Mlooper.mqueue; Mcallback=callback; Masynchronous=Async }
... }

As you can see, when the handler is created without specifying looper, it is bound to the current thread by default. When we go directly to new handler in activity, we are bound to the main thread.

So the whole process is, when the Android program starts, the main thread will start, and then start the main thread of the message loop, that is, Looper.loop (), so the default new handler out of the object, will send the message to the main thread of the MessageQueue. When a child thread is created, it does not start the message loop by default, and if it wants to do message processing, it must proactively start the message loop and generate its own message queue. The Loop method in Looper:

  Public Static voidLoop () {FinalLooper me =Mylooper (); ...        FinalMessageQueue queue =Me.mqueue;  for (;;) {Message msg= Queue.next ();//might block            if(msg = =NULL) {                //No message indicates that the message queue is quitting.                return;            } msg.target.dispatchMessage (msg);        ... msg.recycle (); }

After the loop method is called, the action to distribute and recycle the message begins, Handler.dispatchmessage:

     Public void DispatchMessage (Message msg) {        ifnull) {            handlecallback (msg);         Else {            ifnull) {                if  (Mcallback.handlemessage ( msg) {                    return;                }            }            Handlemessage (msg);        }    }

First check whether the Runnable interface of the message is empty, and then check if the handler callback is empty, and if all is empty, enter the Handlermessage method to handler, because of the polymorphic reason, Will eventually jump to our rewritten handlermessage () method inside!

After reading the feeling: Since each message has a handler object as target, and we can bind a lot of handler to the main thread of the message queue, so as long as the interface a handler, you can send a message to interface A, Go inside the message handler of interface A! Is it a bit like a Windows window handle,:-), which is the way I used to notify the Android interface at the time of the subsequent JNI call.

Message processing for Android

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.