Handler消息机制

Android的消息机制主要是指Handler的运行机制,也就是Handler、Message、MessageQueue、Looper、ThreadLocal之间的工作过程。

Handler:主要用于发送和处理消息。

Message:在线程之间传递消息。

MessageQueue:消息队列,主要用于存放所有通过Handler发送的Message,每个线程中只会有一个MessageQueue对象。

Looper:循环器,调用Looper.loop()方法后,就会进入无限循环中,每当发现MessageQueue中有新消息后就会把它取出来传递到Handler中去处理,每个线程中只有一个Looper对象。

ThreadLocal:存储一些以线程为作用域的数据,线程内部获取到的存储数据是唯一的,不同线程获取到的存储数据是不同的。

MessageQueue

MessageQueue主要包含enqueueMessage()插入和next()读取两个操作,执行读取操作的时候会把读取到的Message从MessageQueue中删除。MessageQueue的内部是通过一个单链表的数据结构来维护的。

enqueueMessage():主要操作是在这个单链表中存储Message。

next():是一个无限循环的方法,如果MessageQueue中没有消息,就一直阻塞在那里,当有新消息来的时候,就会把新消息返回并将该消息从MessageQueue中移除。

quit(boolean safe):将mQuitting属性置为true,这样next()方法就会返回null。

Looper

Handler的工作需要Looper,没有Looper的线程会报错,我们通过Looper.prepare()方法即可为当前线程创建一个Looper,然后通过Looper.loop()开启消息循环。在Looper的构造方法中我们可以看到,会创建一个MessageQueue对象,然后将当前线程保存起来。

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
}

looper最重要的一个方法是loop(),调用了loop()方法以后,消息机制才真正的循环起来。在loop方法中,会调用MessageQueue.next()方法取出一条消息msg,msg为null则跳出循环,msg为null也是唯一跳出循环的方法。msg不为null,则会调用msg.target.dispatchMessage(msg)方法,msg.target是发送这条消息的Handler对象,最终将消息交给Handler来处理了。

quit():调用MessageQueue.quit(false)

quitSafely():调用MessageQueue.quit(true)

Handler

发送消息:

handler有两种发送消息的方式,handler.sendMessage(Message)和handler.post(Runnable),post方法发送消息最终也是通过send方法完成的。可以看到,发送消息的过程调的是MessageQueue.enqueueMessage(Message)方法向单链表中插入一条消息。

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

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);
}

处理消息:

Looper通过loop()方法接收到消息后,会调用Handler的dispatchMessage(Message)方法。如果是通过post方法发送的消息,msg.callback!=null,最终会调run()方法处理消息。如果是通过send方式发送的消息,会调用handleMessage()方法处理消息。

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

 private static void handleCallback(Message message) {
        message.callback.run();
 }

mCallback!=null的情况是我们创建Handler对象的时候是通过如下方式创建的

Handler handler=new Handler(new Handler.Callback(){
        @Override
        public boolean handleMessage(Message message) {
            return false;
        }
});

在Handler的构造方法中,会判断当前线程中是否有Looper,如果没有Looper会抛出"Can't create handler inside thread that has not called Looper.prepare()",在主线程中我们没有做这些操作是因为主线程已经帮我们做了这些操作。所以在子线程中创建Handler的正确方式是:

new Thread() {
            @Override
            public void run() {
                super.run();

                Looper.prepare();
                Handler handler = new Handler() {
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                    }
                };
                Looper.loop();

            }
 }.start();

发送消息过程流程图:Handler消息机制_第1张图片

接收消息过程流程图:

Handler消息机制_第2张图片

 

你可能感兴趣的:(Handler消息机制)