前置知识:ThreadLocal 不懂请进入 一> ThreadLocal
强、虚、软,弱 一> 传送门
执行流程
handler、looper、queue 的 联系 先看图片
主线程(即UI线程)自身就有message loop,不需要创建,ActivityThread 作为 Android的程序启动入口,他为我们自动创建了一个looper,然后在使用looper.loop( ); 这个是调用looper的循环器,不断取出消息。
其他线程就需要手动创建,使用prepare()创建loop,使用 loop()来启动loop,直到 loop 停止。
一个handler 对应有一个 queue(一个线程一个实例化handler),每一个 queue 对应有一个 looper,looper其归属于其创建的地方。
为了维护各个线程的 looper 能够 互相不干扰存储 和 修改数据,ThreadLocal 起到了至关重要的作用
下文的主线是根据handler的构造方法来进行的,先看如下一段代码
一、
public Handler() {
this(null, false);
}
默认执行handlemessage,案例代码。
Handler mhandler= new Handler(){
@Override
public void handleMessage(Message msg) {
Log.e("handleMessage: ","hello world" );
super.handleMessage(msg);
}
};
二、
public Handler(Callback callback) {
this(callback, false);
}
执行上图中的第二个方法。实现回调Callback接口的方法,案例代码。
三、
public Handler(Looper looper) {
this(looper, null, false);
}
在子线程的创建的handle,此时并且拥有自己的 looper,queue,案例代码。
private Handler myhandler;
Thread mthread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
myhandler = new Handler(Looper.myLooper());
Looper.loop();
}
});
此后运用这个handler对象,来进行传递信息,就是存储在子线程中的queue当中。
这里也可以使用 HandlerThread 来使用,更加简洁 一> HandlerThread
四、
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
此处根据上面总结可得
六、
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
MessageQueue
他的数据结构是使用单链表来合成的 ,插入,删除也都是一样的。enqueueMessage()方法。
handler.sendMessage(msg) vs handler.post(runnable)
post(r)方法调用了sendMessageDelay(msg),将runnable任务包装成了msg的Callback属性
handle.dispatchMessage()首先判断msg的Callback是否为空
若不为空,则执行run()方法,否则才执行handleMessage()方法
其实通过 post 方法传递过来的 Runable 方法,也是把它转化成Callback 类型,从而也跟sendMessage执行相同的操作。
post(Ruunable r)
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
避免出现内存泄漏
将 Handler 声明为静态类,并持有一个对 Activity 的弱引用。
static class MyHandler extends Handler {
WeakReference<Activity > mActivityReference;
MyHandler(Activity activity) {
mActivityReference= new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
final Activity activity = mActivityReference.get();
if (activity != null) {
mImageView.setImageBitmap(mBitmap);
}
}
}
若泄漏是因为 Handler 被 delay 的 Message 持有了引用,可在 Activity 的 onDestroy() 中执行 mHandler.removeCallbacks() 方法
下面两篇文章的源码写得挺好的,有空大家可以看一看