在使用Handler更新UI的时候,我是这样写的:
看起来很正常的,但是 Android Lint 却给出了警告: This Handler class should be static or leaks might occur 意思是说:这个Handler 必须是static的,否则就会引发内存泄露。 其实,对于这个问题,Android Framework 的工程师 Romain Guy 早已经在Google论坛上做出过解释,并且给出了他的建议写法:
I wrote that debugging codebecause of a couple of memory leaks I found in the Android codebase. Like yousaid, a Message has a reference to the Handler which, when it's inner and non-static,has a reference to the outer this (an Activity for instance.) If the Message lives in the queuefor a long time, which happens fairly easily when posting a delayed message forinstance, you keep a reference to the Activity and "leak" all theviews and resources. It getseven worse when you obtain a Message and don't post it right away but keep it somewhere(for instance in a static structure) for later use.
他的建议写法是:
下面,我们进一步解释一下: 1.Android App启动的时候,Android Framework 为主线程创建一个Looper对象,这个Looper对象将贯穿这个App的整个生命周期, 它实现了一个消息队列(Message Queue),并且开启一个循环来处理Message对象。而Framework的主要事件都包含着内部 Message对象,当这些事件被触发的时候,Message对象会被加到消息队列中执行。 2.当一个Handler被实例化时(如上面那样),它将和主线程Looper对象的消息队列相关联,被推到消息队列中的Message对象将 持有一个Handler的引用以便于当Looper处理到这个Message的时候,Framework执行Handler的handleMessage(Message)方法。 到底内存泄露是在哪里发生的呢?以下面代码为例:
当Activity被finish()掉,Message 将存在于消息队列中长达10分钟的时间才会被执行到。这个Message持有一个对Handler的引用,Handler也会持有一 个对于外部类(SampleActivity)的隐式引用,这些引用在Message被执行前将一直保持,这样会保证Activity的上下文不被垃圾回收机制回收,同时也会 泄露应用程序的资源(views and resources)。 如果你需要在Handler中调用外部Activity的方法,就让Handler持有一个对Activity的WeakReference,这样就不会泄露Activity的上下文了,如下所示:
总结: 要避免使用非静态的内部类,这种情况,就使用一个静态内部类,同时持有一个对Activity的WeakReference。 参考: [1]https://groups.google.com/forum/?fromgroups=#!msg/android-developers/1aPZXZG6kWk/lIYDavGYn5UJ [2]http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html 原文地址:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1106/1922.html |