android Looper Handler机制

在具体看源码之前,我已经知道了MyMessage中有一个成员变量Handler target来保存handle,于是我写一个简易模拟程序。
考虑因素如下:
1、应用程序无论是哪个MyHandler sendMessage过来的,都可以用一个looper进行处理。
2、MyLooper要有不断提取消息和处理消息的能力,那么要继承Thread。使用一个List list来存储消息,run方法不断取和获取MyMessage中的target,调用handlerMessage方法即可。
类图大概是这样的:
这里写图片描述

当你想强行加一些prepare、loop等函数的时候,你会觉得很鸡肋。
而且考虑到多线程虽然用同一个MyLooper可行,但是每个线程的生命周期和处理的时间不一,不应该采用一个MyLooper对象。带着一些疑问我们看看源码是怎么写的。
1、Handler如何获取Looper中的消息队列
默认构造函数调用this(null, false);

Handler.java
public Handler(Callback callback, boolean async) {
        ...
        mLooper = Looper.myLooper();
        mQueue = mLooper.mQueue;
}

Looper.myLooper();是获取当前线程的Looper对象,此对象有成员mQueue。
handle算了与消息队列联系起来了,方法sendMessage调用了enqueueMessage,将消息放去队列

Handler.java
 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        ...
        return queue.enqueueMessage(msg, uptimeMillis);
}

2、那Looper是怎么跟当前线程形成一对一关系的

Looper.java
private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

可见prepare就是为了创建Looper,然后与当前线程绑定。
Looper类中成员变量static final ThreadLocal sThreadLocal = new ThreadLocal(); 保存着线程和对应looper对象。
之前handle构造函数的Looper.myLooper();语句,其实是

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

sThreadLocal.get(); 返回当前线程looper对象。
3、所以Looper中loop方法先要获取当前线程looper对象,然后得其消息队列。

 public static void loop() {
        final Looper me = myLooper();
        ...
        for (;;) {
            Message msg = queue.next(); // might block
            ...
            msg.target.dispatchMessage(msg);
            ...
            msg.recycle();
        }
    }

4、Handle消息处理顺序

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

先msg的回调方法,再就是handle自身回调方法,最后是handleMessage方法.

自此我们了解了Looper Handle机制”是什么”,但更值得思考的是”为什么”。
5、一对一的对应关系可以采用组合的方式实现,即线程里面有Looper成员变量,应思考设计中的高内聚低耦合

发布了102 篇原创文章 · 获赞 14 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/fofu33/article/details/47280575