怡怡给大家谈谈handler使用,以及handler使用方法应用的知识点,希望对你所遇到的问题有所帮助。

handler使用 handler使用方法handler使用 handler使用方法


handler使用 handler使用方法


handler使用 handler使用方法


1、在开发过程中,我们经常会遇到这样一种情况,当在Activity中使用handler时,直接创建匿名内部类,会得到一个,意思是可能出现内存泄漏,使用静态内部类。

2、这也是面试时经常被问的一个问题,现在,我们就来解读一下为什么会出现这个,以及如何改进。

3、我们知道,Handler在使用时,通过t或者send的方式,可以把消息发送到MessageQueue队列中,期间Looper循环取出消息去交给对应的handler所在的线程去处理,有些消息还加上了延时发送,这些原因就可能会导致一个问题:当Activity销毁了,而主线程中一直运行的Looper会持有handler的引用,而我们在创建handler的时候用的是非静态匿名内部类,所以此handler会持有Activity的引用,导致Activity不会被回收,出现了内存泄漏。

4、因此,编译器才会给我们一个这样的。

5、可能有些朋友会疑惑为什么Looper会持有handler的引用,这就要看源码了:不管我们调用t还是send方式发送消息,最终调用的都是sendMessageAtTime方法,而在这个方法中调用了enqueueMessage方法,我们来看一下Handler中enqueueMessage的源码:可以看到msg.target被赋值给本类对象,也就是我们在activity中创建的handler。

6、也就是说我们在发送Message时,这个消息就把handler给封装进了自己的内部,只要Message对象不被销毁,此handler对象就会一直存在,而此Message会一直存储在MessageQueue消息队列中,直到Looper取出交给handler处理。

7、可以看到Looper的loop()方法的源码如下:交给handler处理完后会回收该消息:这样Looper才能断开与Handler对象的引用,直到这个时候,外部的Activity才可能被回收。

8、因此,在使用handler的时候,不建议再这么使用了。

9、那么我们该怎样正确的使用呢?可以将Handler声明为Activity里的一个静态内部类,内部创建一个WeakReference,将Activity实例用弱引用存起来,这样就可以了。

10、如果为了方便复用,也可以将Handler单独提出来作为一个类,原理相同。

11、如下:采用静态内部类或者单独提出来的作用是让handler对象不再持有activity对象的引用,而对外部activity的使用都是采用弱引用的方式,当回收器发现此activity只有弱引用时,就会回收它,这样就不会导致内存泄漏了。

12、好了,这个问题就解读到这里。

13、下面我们再来看看一些相关的题外知识。

14、我们平常在使用Looper的时候,必须先调用Looper.prepare()方法,因为此方初始化一个Looper(并初始化一个MessageQueue)并和当前线程绑定,只有这些初始化工作完成后,后边我们才能使用这些东西;然后需要调用Looper.loop()把MessageQueue消息队列在这个线程中运行起来。

15、下面是prepare方法和创建looper实例的源码,其中sThreadLocal.set(new Looper(quitAllowed)实现了当前线程和looper的绑定。

本文到这结束,希望上面文章对大家有所帮助。