首先,他们仨是啥?先简单总结一下:
1.Looper
负责在所给定线程里run起一个消息循环,往简单说它就弄了个死循环,不停在message queue里取消息,有消息就处理消息,没消息就阻塞
这一切是在Loop.loop()实现的,注意,它是这个类的静态方法,简单看一下这个方法的实现,我摘取了重要的几行:
public static Looper myLooper() {
return sThreadLocal.get();//ThreadLocal类,对不同线程不同实例的类,这里对ThreadLocal类的应用也是Looper设计的精髓所在
}
public static void loop() {
final Looper me = myLooper();//获取当前线程的Looper对象
final MessageQueue queue = me.mQueue;
for (;;) {//死循环
Message msg = queue.next(); // might block阻塞在这里面实现
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
msg.target.dispatchMessage(msg);//target就是handler
msg.recycleUnchecked();//回收Message对象,将属性归零,将此message对象作为链表头
}
}
另一个重要的static方法,Looper.prepare(),其实就是为当前线程创建一个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));
}
2.Message
本质上是个链表,next对象指向message池中的第一个可用message,至于为啥要节约使用message对象,要弄个缓存池我没理解
其中MessageQueue被Looper引用,当next方法被调用时,使用nativePollOnce实现无消息时的阻塞
3.Handler
起到分发和处理的作用,怎么知道哪个message给哪个handler处理呢?message里面的target属性,就是指向处理者Handler。其比较重要的几个方法:
A.构造new Handler()会获取当前线程所在looper对象,那么就有个要求啦,必须是一个prepare过的Looper,因为如果不prepare过,那当前线程的looper对象是没有建立的,这点对于主线程来说,在ActivityThread中早就调用过Looper.prepareMainThread(),因此主线程可以随便new handler不会报错,但是在其他线程就不能这么任性了。
B.sendMessage
其实就是把message放到message queue里面
C.obtainMessage
调用了Message.obtain()方法,新建或重用一个message对象
D.dispatchMessage & handleMessage
Looper的loop方法中调用dispatchMessage
一般都会重写handleMessage方法来处理收到的message,如果message自带callback那就用message自己的callback
其次,为啥会有经典的内存泄漏问题呢?
如果我们在Activity里面写个子类MyHandler extends Handler,这样呢就会遇到一个经典的内存泄漏问题啦
因为java的内部类会持有对外部类的引用,而message对象的target又持有handler的引用,一旦我们发送一个延迟处理的消息,就会导致关闭Activity的时候无法回收Activity对象,从而造成泄漏啦。处理的方法,要么就写成一个静态内部类,让handler不要引用Activity,要么就在activity的onDestroy()方法里调用在activity的onDestroy()方法里调用handler.removeCallbacksAndMessages(null);把message神马的都清空,就没事了
再次,HandlerThread是个什么鬼?
其实它很简单,它从源码上看,和Handler没啥关系,就是一个带Looper的Thread,就这么简单,那为啥叫HandlerThread呢?因为Handler要用它的Looper啊,就这么简单的关系。
它能干点啥呢?排队嘛,因为message是一个个的处理的,所以这个非常适合在work thread中需要一个个依序排队处理请求的情况。
网友评论