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 方法。

posted @ 2016-08-21 12:27  心夢無痕  阅读(173)  评论(0编辑  收藏  举报