Handler message logoff statement

Source: Internet
Author: User

There are many and thorough descriptions of this topic on the Internet, such:

Http://www.cnblogs.com/xirihanlin/archive/2011/04/11/2012746.html

Http://disanji.net/2011/01/23/android-looper-handler-thread/

Http://zhoujianghai.iteye.com/blog/1097156

In the process of using handler, the following should be the most:

Mhandler. sendmessage (MSG,...); (1)

Mhandler. Post (mrunnable); (2)

I believe that the first sentence can be used every day. Here message is not the key. It is just an object defined and understood as a JavaBean. The most basic reason for using this sentence is that the UI thread implements logoff, the message is distributed by logoff, and handler is used for processing. There are several questions:

1. How does mhandler bind logoff.

2. How does logoff send a message to handler for processing.

3. Message Management.

Let's take a look at the sendmessage Implementation of handler:

    public boolean sendMessageAtTime(Message msg, long uptimeMillis)    {        boolean sent = false;        MessageQueue queue = mQueue;        if (queue != null) {            msg.target = this;            sent = queue.enqueueMessage(msg, uptimeMillis);        }        else {            RuntimeException e = new RuntimeException(                this + " sendMessageAtTime() called with no mQueue");            Log.w("Looper", e.getMessage(), e);        }        return sent;    }

This does not explain question 1, but we can see some 3.

Most of my implementations use handler defined as follows:

     Handler myHandler = new Handler() {            public void handleMessage(Message msg) {                  switch (msg.what) {                       case xxxx:                            break;                  }                  super.handleMessage(msg);             }        }; 

Of course, Handler has other initialization methods, which are temporarily put aside. Let's take a look at handler's definition:

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 shocould be static or leaks might occur:" + Klass. getcanonicalname () ;}// this part can be ignored. find_potential_leaks = false mloaks = Looper. mylooper (); If (mloexception = NULL) {Throw new runtimeexception ("can't create handler inside thread that has not called loled. prepare () ");} mqueue = mloue. mqueue; mcallback = NULL ;}

Here we can see some problems. First, Handler binds a logoff (which is unknown), and The logoff corresponds to a messagequeue.

Continue Viewing:

    public static final Looper myLooper() {        return (Looper)sThreadLocal.get();    }

The following code is clearer:

    private static final ThreadLocal sThreadLocal = new ThreadLocal();    private Looper() {        mQueue = new MessageQueue();        mRun = true;        mThread = Thread.currentThread();    }    public static final void prepare() {        if (sThreadLocal.get() != null) {            throw new RuntimeException("Only one Looper may be created per thread");        }        sThreadLocal.set(new Looper());    }

At this point, the overall structure has revealed a majority.

The logoff function provided by the android API is as follows:

  class LooperThread extends Thread {      public Handler mHandler;      public void run() {          Looper.prepare();          mHandler = new Handler() {              public void handleMessage(Message msg) {                  // process incoming messages here              }          };          Looper.loop();      }  }

We may guess that this is also true in the UI thread. It will be mentioned later.

At this point, we have clearly explained Question 1. How is handler bound to the Logoff of the UI thread? It also shows that each thread can only correspond to one logoff. At the same time, logoff can only correspond to one messagequeue. Therefore, defining multiple handler does not have any efficiency significance except for being clear.

Continue to the second problem. The sendmessage implementation already exists. The target is the target program that processes the message.

Digging down:

    final boolean enqueueMessage(Message msg, long when) {        if (msg.when != 0) {            throw new AndroidRuntimeException(msg                    + " This message is already in use.");        }        if (msg.target == null && !mQuitAllowed) {            throw new RuntimeException("Main thread not allowed to quit");        }        final boolean needWake;        synchronized (this) {            if (mQuiting) {                RuntimeException e = new RuntimeException(                    msg.target + " sending message to a Handler on a dead thread");                Log.w("MessageQueue", e.getMessage(), e);                return false;            } else if (msg.target == null) {                mQuiting = true;            }            msg.when = when;            //Log.d("MessageQueue", "Enqueing: " + msg);            Message p = mMessages;            if (p == null || when == 0 || when < p.when) {                msg.next = p;                mMessages = msg;                needWake = mBlocked; // new head, might need to wake up            } else {                Message prev = null;                while (p != null && p.when <= when) {                    prev = p;                    p = p.next;                }                msg.next = prev.next;                prev.next = msg;                needWake = false; // still waiting on head, no need to wake up            }        }        if (needWake) {            nativeWake(mPtr);        }        return true;    }

Here, the message is added to messagequeue and does not process the message. When will it be processed? I do not know yet, but the when is described here.

In the preceding thread, logoff. Loop () is enabled (). This is an endless loop.

    public static final void loop() {        Looper me = myLooper();        MessageQueue queue = me.mQueue;                // Make sure the identity of this thread is that of the local process,        // and keep track of what that identity token actually is.        Binder.clearCallingIdentity();        final long ident = Binder.clearCallingIdentity();                while (true) {            Message msg = queue.next(); // might block            //if (!me.mRun) {            //    break;            //}            if (msg != null) {                if (msg.target == null) {                    // No target is a magic identifier for the quit message.                    return;                }                if (me.mLogging!= null) me.mLogging.println(                        ">>>>> Dispatching to " + msg.target + " "                        + msg.callback + ": " + msg.what                        );                msg.target.dispatchMessage(msg);                if (me.mLogging!= null) me.mLogging.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("Looper", "Thread identity changed from 0x"                            + Long.toHexString(ident) + " to 0x"                            + Long.toHexString(newIdent) + " while dispatching to "                            + msg.target.getClass().getName() + " "                            + msg.callback + " what=" + msg.what);                }                                msg.recycle();            }        }    }

The core is msg.tar get. dispatchmessage (MSG );

Here I would like to open a sentence. When I was doing a launcher, I started to run an animation with handler at startup, which would be very slow and cause messages to be lost, I think it may be the same as message MSG = queue. next (); // related to the might block. Let's talk about it later.

Msg.tar get is the previous handler.

    public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }

So far, the entire process has ended. Question 3 can also be partially answered. The message will add itself to messagequeue and wait for the loop's round robin. The detailed implementation of messagequeue is of little significance.

The above is a description of mhandler. sendmessage (MSG). Another post runnable method of handler is also described as follows:

    public final boolean post(Runnable r)    {       return  sendMessageDelayed(getPostMessage(r), 0);    }

    private final Message getPostMessage(Runnable r) {        Message m = Message.obtain();        m.callback = r;        return m;    }

This method is directly integrated into the first one. Finally:

    public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }

Even new thread training fails. It's called runnable.

Sort it out:

1. A thead corresponds to a loose,

2. A loose manages a messagequeue.

3. handler can have multiple, but there is no difference between handler and handler.

To put it bluntly:

Put messages in a message queue and wait for the loop to be extracted and processed one by one. No.

Some of the problems we mentioned above are based on a hypothesis:

Android manages an application. An application has a process with a UI thread, which starts the corresponding logoff. This is basically confirmed, but the problem cannot be explained if there is no code here, which will be discussed throughout the application startup process.

Other questions:

1. Some of the logoff class methods have content about main thread. When will this main thread be used? Don't forget, the UI thread is also called main thread.

2. when I was doing a launcher, I started to run an animation with handler at startup, which would be very slow and cause loss of messages. I think it may be different from message MSG = queue. next (); // related to the might block. this is important.

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.