深入理解Looper

小虫
2020-04-22 / 0 评论 / 216 阅读 / 正在检测是否收录...

先看一个Looper使用范例:

class LooperThread extends Thread{
    public Handler mHandler;
    public void run(){
        Looper.prepare();
        mHandler = new Handler(){
            public void handleMessage(Message msg){
                //处理消息
            }
        };
        Looper.loop();//进入主循环
    }
}

这段代码有三个步骤:
1.Looper的准备工作(prepare)
2.创建handler
3.Looper开始动行(loop)

这里会有些疑问,Looper的对象是怎么创建的;handler是如何把message传给MessageQueue的。
查看Looper代码,里面有个非常重要的成员变量

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

这是一个静态常量,一旦import了Looper,sThreadLocal就会构建完毕。ThreadLocal对象是一种特殊的全局变量,因为它的“全局”性只限于自己所在的线程,而外界所有线程无法访问它,这也说明了每个线程的Looper都是独立的。在Looper.prepare中sThreadLocal会创建一个Looper对象。

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

接下来创建一个Handler对象

public Handler mHandler;
mHandler = new Handler(){
    public void handleMessage(Message msg){
                ...
    }
};

handler根据构造函数跟Looper关联起来的,比如:

public Handler();
public Handler(Callback callback);
public Handler(Looper looper);
public Handler(Looper looper,Callback callback);

这里来看下第一个构造函数

public Handler(){
    ...//省略部分代码
    mLooper = Looper.myLooper();//还是通过sThreadLocal.get来获取当前线程中的Looper实例
    ...
    mQueue = mLooper.mQueue;//mQueue是Looper与Handler之间沟通的桥梁
    mCallback = null;
}
这样Handler和Looper,MessageQueue就联系起来了,后续handler执行Post/Send两个类型的函数时,会将消息传递到mQueue中,一旦Looper处理到这一消息,它又会从中调用Handler来进行处理。
0

评论 (0)

取消