Message processing for Android analytics

Source: Internet
Author: User

Pre-order: Each app corresponds to a process, which has a activitythread thread called the main thread (i.e. the main thread of the UI), in addition to other threads, this re-argument.

Android's message system analysis.

    1. Each thread corresponds to only one looper
    2. Each looper corresponds to only one MessageQueue
    3. n a message in each MessageQueue
    4. Specify a maximum of one handler per message to handle events
    5. A thread can correspond to multiple handler

The Looper is responsible for extracting messages (message/runnable) from the message queue (MessageQueue) and handing them over to handler.

Message:

Public final class Message implements Parcelable {
public int what;//Each message can specify a handler, because there can be more than one handler, with what to identify the specific handler public int arg1; public int arg2; public Object obj; Public Messenger ReplyTo; /*package*/static final int flag_in_use = 1 << 0; /*package*/static final int flag_asynchronous = 1 << 1; /*package*/static final int flags_to_clear_on_copy_from = Flag_in_use; /*package*/int flags; /*package*/long when; /*package*/Bundle data; /*package*/Handler target;//Specifies which Handler to handle this message/*package*/Runnable callback ; /*package*/message next;//messages chain private static final Object Spoolsync = new Object (); private static message spool;//header of the message list, note is static private static int spoolsize = 0; private static final int max_pool_size = 50;

......

}

MessageQueue is actually an operational encapsulation of the message, and the message queue is a spool-led list of messages:

Public class MessageQueue {//True if the message queue can be quit. Private Final Boolean mquitallowed; @SuppressWarnings ("unused") private int mptr; Used by native code message mmessages;//message ... private final arraylist<idlehandler> midlehandlers = new Arra Ylist<idlehandler> (); Private idlehandler[] mpendingidlehandlers; Private Boolean mquiting; Indicates whether next () is blocked waiting in pollonce () with a Non-zero timeout. Private Boolean mblocked; The next barrier token. Barriers is indicated by messages with a null target whose arg1 field carries the token. private int mnextbarriertoken;
//Call native function to do real processing private native void Nativeinit (); Private native void Nativedestroy (); Private native void nativepollonce (int ptr, int timeoutmillis); Private native void Nativewake (int ptr);
......

}

Looper:

public class Looper {    private static final String TAG = "Looper";    Static final threadlocal<looper> sthreadlocal = new threadlocal<looper> ();//thread-related template class    private static Looper Smainlooper;  Static type, only one    final MessageQueue Mqueue;//looper holds the MessageQueue    final Thread mthread;    Volatile Boolean mrun;    Private Printer mlogging;

......

}

  

Handler:

The public class handler{//is really the class that handles the message: including handling message and pressing the message into the MessageQueue queue    final MessageQueue mqueue;    Final Looper Mlooper;    Final Callback Mcallback;    IMessenger Mmessenger, ...}

  

Loop () Loops for looper:

    public static void Loop () {final Looper me = Mylooper (); if (me = = null) {throw new RuntimeException ("No Looper;        Looper.prepare () wasn ' t called on this thread. ");        Final MessageQueue queue = Me.mqueue;        Binder.clearcallingidentity ();        Final Long ident = Binder.clearcallingidentity (); for (;;)                {//message loop msg = Queue.next ();//might block//get a message if (msg = = NULL) {///message body is empty indicates exit                No message indicates that the message queue is quitting.            Return }//This must is in a local variable, in case a UI event sets the logger Printer logging = Me.mlogg            ing                        if (logging! = null) {logging.println (">>>>> dispatching to" + Msg.target + "" +            Msg.callback + ":" + msg.what); } msg.target.dispatchMessage (msg);//invokes the message specified by the recipient handler to handle it if (logging! = null){logging.println ("<<<<< finished to" + Msg.target + "" + msg.callback);             }//Make sure that during the course of dispatching the//identity of the thread wasn ' t corrupted.            Final Long newident = Binder.clearcallingidentity (); if (ident! = newident) {LOG.WTF (TAG, "Thread identity changed from 0x" + Long.tohex                        String (ident) + "to 0x" + long.tohexstring (newident) + "when dispatching to"            + Msg.target.getClass (). GetName () + "" + Msg.callback + "what=" + msg.what); } msg.recycle ();//Discard Message, recycle}}

The handler takes a message each time it is fetched from spool (the static message type in message), which invokes the static method:

    public static Message obtain (Handler H, int. what, Object obj) {        Message M = obtain ();        M.target = h;        M.what = what;        M.obj = obj;        return m;    }

Handler press messages into Message Queuing:

    public boolean sendmessageattime (Message msg, long Uptimemillis)    {        Boolean sent = false;        MessageQueue queue = Mqueue;        if (queue! = null) {            msg.target = this;            Sent = Queue.enqueuemessage (msg, uptimemillis);//Call MessageQueue method to perform a push-in operation        }        else {            runtimeexception E = new RuntimeException (this                + "sendmessageattime () called with no Mqueue");            LOG.W ("Looper", E.getmessage (), E);        }        return sent;    }

Summary: Handler the message is taken directly (from the spool), the message is pressed into the MessageQueue is called MessageQueue method.

----------------------------------------------Split Line------------------------------------------------------------------------ ----

The following is an analysis of when these objects were created.

When was the Looper created?

Each thread has only one Looper object.

1. Normal threads (not the main thread)

A typical self-created thread uses looper such as:

Class Looperthread extends thread{public    Handler Mhandler;    public void Run () {        looper.prepare ();        Mhandler= New Handler () {public                void Handlemessage (Message msg) {                    //processing Messages                }        };        Looper.loop ();//Enter message loop    }}

When was the Looper created? See Looper.prepare () method: After executing this method, we get a unique looper of this thread.

Static final threadlocal<looper> sthreadlocal = new threadlocal<looper> ();//This is a template class that is first closed to the thread    

private static void Prepare (Boolean quitallowed) { if (sthreadlocal.get () = null) {//throws an exception if the caller already has looper on the host thread throw new RuntimeException ("Only one Looper could be created per thread"); } Sthreadlocal.set (New Looper (quitallowed)); thread-local storage in//java, that is, different lines }//to get their own different sthreadlocal object references by Looper

    Private Looper (Boolean quitallowed) {        mqueue = new MessageQueue (quitallowed);//create Looper to process the message queue        Mrun = true;        Mthread = Thread.CurrentThread ();//Get current thread    }

  

So how does handler relate to Looper? See how the handler is constructed:

Public Handler () {        if (find_potential_leaks) {            final class<? extends handler> Klass = GetClass ();            if (Klass.isanonymousclass () | | klass.ismemberclass () | | klass.islocalclass ()) &&                    (Klass.getmodifiers () & modifier.static) = = 0) {                log.w (TAG, "the following Handler class should be STATIC or leaks might occur:" +                    Klass.getcanonicalname ());            }        }        Mlooper = Looper.mylooper ();//through thread-local storage, get the Looper        if (mlooper = = null) of this thread {            throw new RuntimeException (                " Can ' t create handler inside thread that have not called looper.prepare () ");        }        Mqueue = Mlooper.mqueue;        Mcallback = null;    }
    public static Looper Mylooper () {//Get Looper        return Sthreadlocal.get () associated with this thread;    }

  

Summary: Each thread creates a Looper through sthreadlocal<looper> (which in turn creates a MessageQueue), and then creates a handler (via Sthreadlocal). Thus, handler and Looper are "bound" together to form a complete message circulatory system.

2. Main thread Activitythread

When did the main thread create the Looper? In the main method of Activitythread.java, there are:

    public static void Main (string[] args) {        samplingprofilerintegration.start ();        Closeguard.setenabled (false);        Process.setargv0 ("<pre-initialized>");        Looper.preparemainlooper ();//is also Sthreadlocal.set (new Looper (quitallowed)) to create a thread that belongs to the Looper, and through Sthreadlocal.get () assigning Looper to Smainlooper (private static Looper Smainlooper), the Smainlooper function is that other threads can get Looper to the main thread (because Smainlooper is static , which is assigned in the main thread).        if (Smainthreadhandler = = null) {            Smainthreadhandler = new Handler ();        }        Activitythread thread = new Activitythread ();        Thread.attach (false);        Asynctask.init ();        if (false) {            looper.mylooper (). setmessagelogging (New                    Logprinter (Log.debug, "Activitythread"));        }        Looper.loop ();        throw new RuntimeException ("Main thread loop unexpectedly exited");    }

  

Looper.loop () is a static method that, as a message loop processor, constantly takes messages and distributes messages.

Message processing for Android analytics

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.