Android developers than sixteen: Message, MessageQueue, Looper, Handler principle knowledge source analysis

Outline

android handler as an important mechanism for message handling, a comprehensive review of its knowledge involved.

The key class

The entire message handling mechanism main classes are involved: 
the Message: responsible for message encapsulation 
MessageQueue: responsible for encapsulating message to the message queue 
Looper: responsible for getting messages from the message queue and distributed 
Handler: process responsible for sending the message and

Message

Look like comments in the code:

Comprising message definition and any description data objects, sending to the Handler. The object contains two additional int field and one additional object field, it does not allow you to assign new objects in many cases. 
While the Message constructor is common, but the best method is to call Message.obtain () or Handler.obtainMessage () method, a Message object acquired from the buffer pool.

Speaking quite clearly, Mesasge duty is to wrap the data cache and generate Message. 
Then take a look at the key field and methods of Message object:

public final class Message implements Parcelable {

    //在handler处理消息时,用于区分消息内容
    public int what;
    //可携带int参数
    public int arg1; 
    //可携带int参数
    public int arg2;
    //包装的消息对象
    public Object obj;

    //缓存池对象
    private static Message sPool;
    Message next;
    private static int sPoolSize = 0;
    //缓存池的大小
    private static final int MAX_POOL_SIZE = 50;

     //从全局的缓存池中获取一个新的Mesasge实例,避免分配新的对象
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

    //Message本身携带了target对象,也就是目标handler
    //因此消息可以通过target进行发送
    public void sendToTarget() {
        target.sendMessage(this);
    }
//message对象的回收缓存
void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        sendingUid = -1;
        when = 0;
        target = null;
        callback = null;
        data = null;

        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }
}


SPOOL is a linked list structure, in Obtain () method, is empty, the SPOOL simply returns a new Message object, if not empty, then it returns the current object taken, note that the method using synchronized code block synchronization. 
Message which there are some other methods, are used to assist the basic construction and Message cache, not listed here.

MessageQueue

Look like comments in the code:

Low-level classes, contains a list of messages to be dispatched by Looper. Messages are not directly added to the MessageQueue, but by Handler object associated with Looper. 
You can use Looper.myQueue () retrieves the current thread MessageQueue.

Looper to schedule a class, Message Handler object to be processed by the MessageQueue placed. 
The key fields and methods:

public final class MessageQueue {
    Message mMessages;
    //将Mesage入队
    boolean enqueueMessage(Message msg, long when) {

            //...省略代码
                Message p = mMessages;
             //...省略代码

            if (p == null || when == 0 || when < p.when) {
                //mMessages是空的,或者如果新msg的执行时间为0,或者小于当前mMessages的时间
                //那么msg会成为链表的新头部
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    //一直找到队尾或者执行时间小于找到的message的时间
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                //然后把新的msg插入进去
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            //...省略代码
          }
    }
//获取Message
Message next() {
    //...省略代码
    Message prevMsg = null;
    Message msg = mMessages;
    //...省略代码
      for (;;) {
        if (prevMsg != null) {
           prevMsg.next = msg.next;
       } else {
           mMessages = msg.next;
       }
       msg.next = null;
       if (DEBUG) Log.v(TAG, "Returning message: " + msg);
       msg.markInUse();
       return msg;
    }
}


Overall Looper responsible message enqueue and dequeue, mainly based Message Message execution time to determine the position in the list, the smaller, the more forward position in the queue, the more executed Handler early.

Looper

Class Notes:

For message loop running thread classes. By default, the thread is not associated message loop; call prepare method to create a Looper object to run the loop thread, and then call the loop method of processing messages it until the cycle stops. 
Most of the news cycle by Handler objects will interact.

Means that we can get Looper object of the current thread by Looper.prepare () method. 
The key fields and methods:

public final class Looper {
    //当前线程的ThreadLocal,保存了Looper对象  
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    //application 的主Looper对象,负责整个App的消息处理
    private static Looper sMainLooper;  // guarded by Looper.class
    //消息队列
    final MessageQueue mQueue;

//准备Looper对象
 public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        //使用ThreadLocal来给当前线程设置一个Looper对象
        sThreadLocal.set(new Looper(quitAllowed));
    }

    //Application 的主Looper对象,在ActivityThread这个类中调用该方法来生成Looper
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
}
//获取Application的主Looper对象
 public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }

    //获取当前线程的Looper对象
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

    //获取当前线程的MessageQueue对象
    public static @NonNull MessageQueue myQueue() {
        return myLooper().mQueue;
    }
//从MessageQueue 中取出Message进行分发处理
 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;

        //...省略代码

        for (;;) {
        //获取Message
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

         //...省略代码
            try {
            //使用Message包含的Handler对象进行消息的处理
                msg.target.dispatchMessage(msg);
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {

            }

        //...省略代码
            //回收message
            msg.recycleUnchecked();
        }
    }



From the above it can be seen the primary responsibility Looper object one is generating the entire main Looper objects Applicaion, and run on the UI thread, this step is called in ActivityThread the main () method, if it is in the child thread, then you can generate different Looper object so that each thread has its own Looper objects, message processing is not affected each other. 
Also withdrawn is sent to a Message Handler object corresponding processing from the MessageQueue. 
For some analysis ThreadLocal class: Android ThreadLocal and InheritableThreadLocal analysis.

Handler

Handler in key comments:

Handler has two main purposes:
(1) Arrangement News and runnables will be performed at some point in the future; 
(2) execution messages into the team on your own with a different thread;

The key fields and methods:

public class Handler {

    //通常我们调用该方法来发送消息
    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }
//该方法可以设置消息执行的延迟时间
public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
//该方法可以设置消息在指定的时间点运行
    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }
//最终消息进入MessageQueue的队列
 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
     //这里就将handler的引用传递个message对象了
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
//可以进行Runnable任务
    public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
    //将Runnable任务封装成Message
    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }
    //处理消息,注意msg.callback和mCallback 的特殊情况,尤其是传入了
    //mCallback 的情况下将不会走handleMessage()方法
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

    //子类必须实现该方法来处理消息
    public void handleMessage(Message msg) {  }
}


to sum up

The entire processing flow of execution message:

Handler.sendMesasge ();
Handler.sendMessageDelayed ();
Handler.sendMessageAtTime ();
Handler.enqueueMessage (), so far the enqueue message;
Looper.loop () is removed from the MessageQueue message distributed to the target Handler;
Handler.handleMessage ( )
of course, in the middle of some special handling procedures and pay attention.

Published 377 original articles · won praise 145 · views 210 000 +

Guess you like

Origin blog.csdn.net/Windgs_YF/article/details/104293104