之前一直以为Handler的handleMessage方法总是运行在主线程,归根到底还是没有真正理解Looper的创建过程。
那么问题来了,为什么我们默认创建的Handler会运行在主线程呢?
默认情况下,ActivityThread类为我们创建的了主线程的Looper和消息队列,所以当你创建Handler之后发送消息的时候,消息的轮询和handle都是在UI线程进行的。
关于ActivityThread:默认整个应用程序,都是通过ActivityThread类启动的,在ActivityThread类当中,负责创建我们所有的Activity,并回调每个Activity中的生命周期方法。在ActivityThread类中,默认会去创建一个线程,这个线程叫做main线程(主线程)。所有的应用程序,更新UI的操作,都是在这个main线程中进行的。
再看Looper类中的prepareMainLooper方法
接下来看prepareMainLooper方法的第一行prepare(false)方法
这里我们需要对ThreadLocal类进行一下解释,ThreadLocal在我们的线程当中用于去保存一些变量信息,默认情况下,创建一个与线程相关的一个对象,是通过threadLocal存储的,threadLocal有set和get方法,set是把变量设置到threadLocal当中 ,get方法是获取出来。因为当前线程是UI线程,默认情况下threadLocal是没有存储的,所以为null,所以不走if而是new Looper对象之后在存储。
再回到图2,看最后一行获取MainLooper。
到此为什么我们默认创建的Handler会运行在主线程呢?已经基本明白,如果还不明白可以看看Looper的loop方法。
到这里还没结束,那么怎么在子线程初始化Handler呢?也就是handleMessage方法运行在子线程。
Handler mHandler;
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();//Looper初始化
//Handler初始化 需要注意, Handler初始化传入Looper对象是子线程中缓存的Looper对象
mHandler = new Handler(Looper.myLooper());
Looper.loop();//死循环
//注意: Looper.loop()之后的位置代码在Looper退出之前不会执行,(并非永远不执行)
}
}).start();
也可以调用Android系统的ThreadHandler实现,关于ThreadHandler本篇不做分析,感兴趣可以自己看看源码。
到此本文种重点也就结束了。总结一下:
Handler的handleMessage方法不一定在主线程,取决于Looper所在的线程。