Android Handler的警告Handler Class Should be Static or Leaks Occur
来源:互联网 发布:javascript事件委托 编辑:程序博客网 时间:2024/06/05 14:07
我们使用Handler更新UI的时候,写法如下:
public class MainActivity extends Activity { Handler handler = new Handler() { @Override public void handleMessage(Message msg) { //TODO } };}
Android Lint 给出了警告:This Handler class should be static or leaks might occur
Since this Handler is declared as an inner class, it may prevent the outer class from being garbage collected….
意思是说:这个Handler 被定义为匿名内部类,内部类持有外部类的应用,它会阻止GC对外部类的垃圾回收。
其实,对于这个问题,Android Framework 的工程师 Romain Guy 早已经在Google论坛上做出过解释,并且给出了他的建议写法:
I wrote that debugging code because of a couple of memory leaks I found in the Android codebase. Like you said, 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 queue for a long time, which happens fairly easily when posting a delayed message for instance, you keep a reference to the Activity and “leak” all the views and resources. It gets even 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.
public class MainActivity extends Activity { private static class CustomHandler extends Handler{ private final WeakReference<MainActivity> mTarget; CustomHandler(MainActivity target) { mTarget = new WeakReference<MainActivity>(target); } @Override public void handleMessage(Message msg) { MainActivity activity = mTarget.get(); if (activity != null) { // TODO: 17/3/19 } } }}
解释如下:
1、在 Java 语言中,非静态匿名内部类将持有一个对外部类的隐式引用,而静态内部类则不会。
2、App启动的时候, 在ActivityThread 的main 函数中为主线程创建一个Looper对象,这个Looper对象将贯穿这个App的整个生命周期,它实现了一个 消息队列(Message Queue),并且开启一个循环来处理Message对象。而Framework的主要事件都包含着内部Message对象,当这些事件被触发的 时候,Message对象会被加到消息队列中执行。
3、当一个Handler被实例化时(如上面那样),它将和主线程Looper对象的消息队列相关联,被推到消息队列中的Message对象将持有一个Handler的引用以便于当Looper处理到这个Message的时候,Framework执行Handler的handleMessage(Message)方法。
为什么会发生内存泄露
public class MainActivity extends Activity { private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // TODO: 17/3/19 } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); handler.sendMessageDelayed(Message.obtain(), 10 * 60 * 1000); finish(); }}
当Activity被finish()掉,Message 将存在于消息队列中长达10分钟的时间才会被执行到。这个Message持有一个对Handler的引用,Handler也会持有一个对于外部类(SampleActivity)的隐式引用,这些引用在Message被执行前将一直保持,这样会保证Activity的上下文不被垃圾回收机制回收,同时也会泄露应用程序的资源(views and resources)。
为解决这个问题,下面这段代码中的Handler则是一个静态内部类。静态内部类不会持有一个对外部类的隐式引用,因此Activity将不会被泄露。如果你需要在Handler中调用外部Activity的方法,就让Handler持有一个对Activity的WeakReference,这样就不会泄露Activity的上下文了,如下所示:
public class MainActivity extends Activity { private static class CustomHandler extends Handler{ private final WeakReference<MainActivity> mTarget; CustomHandler(MainActivity target) { mTarget = new WeakReference<MainActivity>(target); } @Override public void handleMessage(Message msg) { MainActivity activity = mTarget.get(); if (activity != null) { // TODO: 17/3/19 } } }}
什么是WeakReference?
WeakReference弱引用,与强引用(即我们常说的引用)相对,它的特点是,GC在回收时会忽略掉弱引用,即就算有弱引用指向某对象,但只要该对象没有被强引用指向(实际上多数时候还要求没有软引用,但此处软引用的概念可以忽略),该对象就会在被GC检查到时回收掉。对于上面的代码,用户在关闭Activity之后,就算后台线程还没结束,但由于仅有一条来自Handler的弱引用指向Activity,所以GC仍然会在检查的时候把Activity回收掉。这样,内存泄露的问题就不会出现了。
- android handler的警告Handler Class Should be Static or Leaks Occur
- Android handler的警告Handler Class Should be Static or Leaks Occur
- android handler的警告Handler Class Should be Static or Leaks Occur问题处理
- Android handler的警告Handler Class Should be Static or Leaks Occur
- android handler的警告Handler Class Should be Static or Leaks Occur
- android handler的警告Handler Class Should be Static or Leaks Occur
- android handler的警告Handler Class Should be Static or Leaks Occur
- android handler的警告Handler Class Should be Static or Leaks Occur
- android handler的警告Handler Class Should be Static or Leaks Occur
- android handler的警告Handler Class Should be Static or Leaks Occur
- Android Handler的警告Handler Class Should be Static or Leaks Occur
- Android“This Handler class should be static or leaks might occur”警告的处理方法
- 关于Android“This Handler class should be static or leaks might occur”警告的处理方法
- 关于Android“This Handler class should be static or leaks might occur”警告的处理方法
- 关于Android“This Handler class should be static or leaks might occur”警告的处理方法
- Android 关于Handler警告处理 This Handler class should be static or leaks might occur
- android之lint警告This Handler class should be static or leaks might occur
- android警告This Handler class should be static or leaks might occur
- 计算机基础
- PAT (Advanced Level) Practise 1001. A+B Format (20)
- 【九度OJ】题目1193:矩阵转置 解题报告
- Codeforces 599D Spongebob and Squares【思维枚举+数学方程】
- 《ACM程序设计》书中题目--problem y
- Android Handler的警告Handler Class Should be Static or Leaks Occur
- BZOJ4405: [wc2016]挑战NPC
- 最大子序列和
- Linux学习日记(2)
- 线性结构_链表
- POJ2407 Relatives 【欧拉函数模板】
- 计算机网络原理之物理层(一)
- 没有使用transformfeedback的粒子系统
- 机房收费系统——【三】软件需求说明书