Android开发常见问题之Handler引起的内存泄漏
来源:互联网 发布:autodesk maya mac 编辑:程序博客网 时间:2024/06/09 15:21
具体内容来自
http://droidyue.com/blog/2014/12/28/in-android-handler-classes-should-be-static-or-leaks-might-occur/
Handler handleProgress2 = new Handler() { public void handleMessage(Message msg) { int position = mediaPlayer.getCurrentPosition(); int duration = mediaPlayer.getDuration(); if (duration > 0) { long pos = skbProgress.getMax() * position / duration; skbProgress.setProgress((int) pos); } } };
这么写的时候AS提示可能导致了内存泄漏
In Android, Handler classes should be static or leaks might occur,
Messages enqueued on the application thread’s MessageQueue also retain
their target Handler. If the Handler is an inner class, its outer
class will be retained as well. To avoid leaking the outer class,
declare the Handler as a static nested class with a WeakReference to
its outer class
1.当一个Android应用启动的时候,会自动创建一个供应用主线程使用的Looper实例。Looper的主要工作就是一个一个处理消息队列中的消息对象。在Android中,所有Android框架的事件(比如Activity的生命周期方法调用和按钮点击等)都是放入到消息中,然后加入到Looper要处理的消息队列中,由Looper负责一条一条地进行处理。主线程中的Looper生命周期和当前应用一样长。
2.当一个Handler在主线程进行了初始化之后,我们发送一个target为这个Handler的消息到Looper处理的消息队列时,实际上已经发送的消息已经包含了一个Handler实例的引用,只有这样Looper在处理到这条消息时才可以调用Handler#handleMessage(Message)完成消息的正确处理。
3.在Java中,非静态的内部类和匿名内部类都会隐式地持有其外部类的引用。静态的内部类不会持有外部类的引用。
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() { /* ... */ } }, 1000 * 60 * 10); // Go back to the previous Activity. finish(); }}
原博客中用这个例子来说明问题。我的理解是因为Handler是一个匿名内部类的实例,隐含着对SampleActivity 的引用,所有finish方法无法将其释放。要解决这种问题,思路就是不适用非静态内部类,继承Handler时,要么是放在单独的类文件中,要么就是使用静态内部类。因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露。当你需要在静态内部类中调用外部的Activity时,我们可以使用弱引用来处理。另外关于同样也需要将Runnable设置为静态的成员属性。注意:一个静态的匿名内部类实例不会持有外部类的引用。 修改后不会导致内存泄露的代码如下。
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; //hold weak activity when init public MyHandler(SampleActivity activity) { mActivity = new WeakReference<SampleActivity>(activity); } @Override public void handleMessage(Message msg) { //gain activity when use 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, 1000 * 60 * 10); // Go back to the previous Activity. finish(); }}
PS:原文中讲Runnable一并设置为静态,避免了这个问题,非常好!
- Android开发常见问题之Handler引起的内存泄漏
- Android开发-Handler引起的内存泄漏-实验、分析、总结。
- Android开发-Handler引起的内存泄漏-实验、分析、总结。
- Android handler 引起的内存泄漏
- android Handler引起内存泄漏
- Android开发内存泄露之--Handler引起的内存泄露
- Android 开发日志——Handler引起内存泄漏
- Android开发--Handler引起的内存泄露
- Android开发 Handler引起的内存泄露
- 解决由Handler 引起的内存泄漏
- 安卓-Handler引起的内存泄漏
- Handler引起的内存泄漏解决办法
- 内存泄漏检测工具和Handler引起的内存泄漏问题
- Android内存泄漏之 handler
- Android 内存泄漏之handler
- Android开发——Handler引起的内存泄露
- 关于Android中Handler引起内存泄漏问题
- Android之“Handler内部类引起的内存溢出警告”
- STM32W108无线ZigBee射频芯片引脚说明(下篇)
- Java程序员应该知道的10个eclipse调试技巧
- 发下牢骚(一)
- Hadoop入门系列(3) -- Eclipse+Hadoop开发环境搭建
- 推荐使用Numba加速Python科学计算
- Android开发常见问题之Handler引起的内存泄漏
- Nexus搭建Maven私服
- Android初学之------检查前置摄像头是否存在
- 解决ACM异常wt.fc.ObjectNoLongerExistsException
- C#中List<T>
- 图片放大缩小
- Java程序设计第十七周之图片的随机显示部分实现
- 7.2 android volley超时重试设置
- 【乐视招贤纳士】Java高级开发工程师