看到一篇关于handler和匿名类关于内存泄露的文章,觉得不错,充分发挥拿来主义,先放这儿看着!

From:http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html

Consider the following code:

public class SampleActivity extends Activity {

  private final Handler mLeakyHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// ...
}
}
}

While not readily obvious, this code can cause cause a massive memory leak. Android Lint will give the following warning:

In Android, Handler classes should be static or leaks might occur.

But where exactly is the leak and how might it happen? Let's determine the source of the problem by first documenting what we know:

  1. When an Android application first starts, the framework creates a Looper object for the application's main thread. ALooper implements a simple message queue, processing Message objects in a loop one after another. All major application framework events (such as Activity lifecycle method calls, button clicks, etc.) are contained inside Messageobjects, which are added to the Looper's message queue and are processed one-by-one. The main thread's Looper exists throughout the application's lifecycle.

  2. When a Handler is instantiated on the main thread, it is associated with the Looper's message queue. Messages posted to the message queue will hold a reference to the Handler so that the framework can callHandler#handleMessage(Message) when the Looper eventually processes the message.

  3. In Java, non-static inner and anonymous classes hold an implicit reference to their outer class. Static inner classes, on the other hand, do not.

So where exactly is the memory leak? It's very subtle, but consider the following code as an example:

public class SampleActivity extends Activity {

  private final Handler mLeakyHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// ...
}
} @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Post a message and delay its execution for 10 minutes.
mLeakyHandler.postDelayed(new Runnable() {
@Override
public void run() { }
}, 60 * 10 * 1000); // Go back to the previous Activity.
finish();
}
}

When the activity is finished, the delayed message will continue to live in the main thread's message queue for 10 minutes before it is processed. The message holds a reference to the activity's Handler, and the Handler holds an implicit reference to its outer class (the SampleActivity, in this case). This reference will persist until the message is processed, thus preventing the activity context from being garbage collected and leaking all of the application's resources. Note that the same is true with the anonymous Runnable class on line 15. Non-static instances of anonymous classes hold an implicit reference to their outer class, so the context will be leaked.

To fix the problem, subclass the Handler in a new file or use a static inner class instead. Static inner classes do not hold an implicit reference to their outer class, so the activity will not be leaked. If you need to invoke the outer activity's methods from within the Handler, have the Handler hold a WeakReference to the activity so you don't accidentally leak a context. To fix the memory leak that occurs when we instantiate the anonymous Runnable class, we make the variable a static field of the class (since static instances of anonymous classes do not hold an implicit reference to their outer class):

public class SampleActivity extends Activity {

  /**
* Instances of static inner classes do not hold an implicit
* reference to their outer class.
*/
private static class MyHandler extends Handler {
private final WeakReference<SampleActivity> mActivity; public MyHandler(SampleActivity activity) {
mActivity = new WeakReference<SampleActivity>(activity);
} @Override
public void handleMessage(Message msg) {
SampleActivity activity = mActivity.get();
if (activity != null) {
// ...
}
}
} private final MyHandler mHandler = new MyHandler(this); /**
* Instances of anonymous classes do not hold an implicit
* reference to their outer class when they are "static".
*/
private static final Runnable sRunnable = new Runnable() {
@Override
public void run() { }
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Post a message and delay its execution for 10 minutes.
mHandler.postDelayed(sRunnable, 60 * 10 * 1000); // Go back to the previous Activity.
finish();
}
}

The difference between static and non-static inner classes is subtle, but is something every Android developer should understand. What's the bottom line? Avoid using non-static inner classes in an activity if instances of the inner class outlive the activity's lifecycle. Instead, prefer static inner classes and hold a weak reference to the activity inside.

内存泄露了么: Handlers & Inner Classes的更多相关文章

  1. JVM内存管理概述与android内存泄露分析

    一.内存划分 将内存划分为六大部分,分别是PC寄存器.JAVA虚拟机栈.JAVA堆.方法区.运行时常量池以及本地方法栈. 1.PC寄存器(线程独有):全称是程序计数寄存器,它记载着每一个线程当前运行的 ...

  2. Android中Handler引起的内存泄露

    在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用.通常我们的代码会这样实现. 1 2 3 4 5 6 7 8 9 public class SampleActivit ...

  3. logging 模块误用导致的内存泄露

    首先介绍下怎么发现的吧, 线上的项目日志是通过 logging 模块打到 syslog 里, 跑了一段时间后发现 syslog 的 UDP 连接超过了 8W, 没错是 8 W. 主要是 logging ...

  4. Android 中 Handler 引起的内存泄露

    在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用.其实这可能导致内存泄露,代码中哪里可能导致内存泄露,又是如何导致内存泄露的呢?那我们就慢慢分析一下.http://w ...

  5. 【转】内部Handler类引起内存泄露

    如果您在Activity中定义了一个内部Handler类,如下代码: public class MainActivity extends Activity {       private  Handl ...

  6. Handler 引起的内存泄露

    先看一组简单的代码 1 2 3 4 5 6 7 8 9 public class SampleActivity extends Activity { private final Handler mHa ...

  7. 【翻译】Android避免内存泄露(Activity的context 与Context.getApplicationContext)

    原谅地址:http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html ,英文原文在翻译之后 Android 应用 ...

  8. Activity内部Handler引起内存泄露的原因分析

    有时在Activity中使用Handler时会提示一个内存泄漏的警告,代码通常如下: public class MainActivity extends Activity { private Text ...

  9. Java内存泄露监控工具:JVM监控工具介绍【转】

    jstack?-- 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程 ...

随机推荐

  1. Entity Framework Power Tools安装和使用

    Entity Framework Power Tools是一个由EntityFramework开发小组提供的工具,它可以从现有数据库生成Fluent款式的Code First代码. 大致来说,这个工具 ...

  2. Android应用市场提交入口

    应用市场是整个移动生态系统的核心,然而对于中国用户来说,Google Play应用商店却因为种种原因,在中国一直无法长期稳定的运作,又加上Android系统的开源特性,从而在中国造就出大量的第三方应用 ...

  3. HTML的标签-W3School读后总结

    学习前端知识有一段时间了,前两天想做个博客园的皮肤的静态页面.虽然做完了,但是有很多不如意的地方,反思一下,还是基础不够好,所以现在把html再过一遍.(这个是Xmind生成的图片)

  4. [resource]23个python的机器学习包

    23个python的机器学习包,从常见的scikit-learn, pylearn2,经典的matlab替代orange, 到最新最酷的Theano(深度学习)和torch 7 (well,其实lua ...

  5. tomcat7.0.47 修改tomcat窗口名称

    最近使用的是 apache - tomcat 集群,为了方便管理上想要修改tomcat命令窗口的名字来区分不同的tomcat,我在网上找了些资料,顺便总结一下,方便自己,方便他人 修改如下: 找到to ...

  6. z-index兼容问题:关于ie6/7下的z-index

    z-index这个属性其实在挺多地方都会用到,在百度上搜索也有大量关于z-index的篇幅去阐述这个属性,特别是在ie6下的z-index处理有更多的相关文章,本文就不再围绕z-index这一属性的基 ...

  7. jquery-validation 学习总结

    一.用前必备 项目主页:http://bassistance.de/jquery-plugins/jquery-plugin-validation/ API: http://jquery.bassis ...

  8. JsRender系列demo(5) for else

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  9. Javascript 中childNodes和children的区别

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  10. java基础知识回顾之javaIO类--内存操作流ByteArrayInputStream和ByteArrayOutputSteam(操作字节数组)

    直接看代码: package cn.itcast.io.p6.bytestream; import java.io.ByteArrayInputStream; import java.io.ByteA ...