Handler 源码分析
Handler用法:
无参 Handler 构造函数实例化一个 Handler 类型的全局变量,并重写其 handleMessage 方法,在某一方法内调用 Handler 的 sendEmptyMessage 或者sendMessage 发送消息,在某一时刻 handleMessage 回调方法会被调用 。
Handler 内部定义的两个 final 对象
final MessageQueue mQueue ; final Looper mLooper ;
MessageQueue 即为其内部的消息队列, mQueue 是通过 Looper 的静态变量 mQueue 直接赋值的。而 mLooper是通过 Looper 的静态方法 myLooper() 赋值。
Looper.myLooper() 实质上调用了 sThreadLocal.get() 来获取与当前线程相关联的 Looper ,源码里面有这样一句话
// sThreadLocal.get() will return null unless you've called prepare().
,在调用该方法之前必须先调用 prepare() 方法,否则该方法返回 null 。但事实上我们并没有调用这个方法,却能成功,原因是为什么呢?
Looper 内部提供了一个静态方法 prepareMainLooper ,这个方法是在应用程序创建的时候直接由 android 系统调用的。
/** Initialize the current thread as a looper, marking it as an application's main * looper. The main looper for your application is created by the Androidenvironment, * so you should never need to call this function yourself. */
该方法调用了 prepare () 方法和 setMainLooper (myLooper ()) 并将 myLooper () 返回的值设置为主线程的 looper 。
接下来看 sendEmptyMessage 和其他几个发送消息的方法,它们最终都会调用到 sendMessageAtTime 这样一个方法,而这个方法会调用 MessageQueue 提供的 enqueueMessage 方法,该方法将发送的消息放入消息队列里面,最后调用
nativeWake(mPtr) 方法,这是一个 C++ 实现的方法,具体的实现内容没有深究,但应该间接调用到 Looper 的loop() 方法。
接下来看一下 loop() 方法,这个方法从消息队列中取出消息,然后调用里面存放的 target 的 dispatchMessage 方法:
msg.target.dispatchMessage(msg);
msg.target 存放的是在构造消息的类的 handler 对象,事实上这里回调了 handler 的 dispatchMessage 方法,该方法会调用 handleMessage 方法。