美文网首页
Handler Looper Message

Handler Looper Message

作者: hiLily | 来源:发表于2017-11-19 20:15 被阅读24次

首先,他们仨是啥?先简单总结一下:

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中需要一个个依序排队处理请求的情况。

相关文章

网友评论

      本文标题:Handler Looper Message

      本文链接:https://www.haomeiwen.com/subject/dlmuvxtx.html