`
bogongjie
  • 浏览: 235994 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

android Handler导致内存泄露分析

 
阅读更多
Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
            // do something.
    }
}

 当我们这样创建`Handler`的时候`Android Lint`会提示我们这样一个`warning: In Android, Handler classes should be static or leaks might occur.`。

 

一直以来没有仔细的去分析泄露的原因,先把主要原因列一下:    
- `Android`程序第一次创建的时候,默认会创建一个`Looper`对象,`Looper`去处理`Message Queue`中的每个`Message`,主线程的`Looper`存在整个应用程序的生命周期.
- `Hanlder`在主线程创建时会关联到`Looper`的`Message Queue`,`Message`添加到消息队列中的时候`Message(排队的Message)`会持有当前`Handler`引用,当`Looper`处理到当前消息的时候,会调用`Handler#handleMessage(Message)`.就是说在`Looper`处理这个`Message`之前,会有一条链`MessageQueue -> Message -> Handler -> Activity`,由于它的引用导致你的`Activity`被持有引用而无法被回收`
- **在java中,no-static的内部类会隐式的持有当前类的一个引用。static的内部类则没有。**

 

public class SampleActivity extends Activity {

  private final Handler mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                  // do something
                }
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
        // 发送一个10分钟后执行的一个消息
        mHandler.postDelayed(new Runnable() {
          @Override
          public void run() { }
        }, 600000);

        // 结束当前的Activity
        finish();
}

 

在`finish()`的时候,该`Message`还没有被处理,`Message`持有`Handler`,`Handler`持有`Activity`,这样会导致该`Activity`不会被回收,就发生了内存泄露.

 

解决方法 
- 通过程序逻辑来进行保护。
    - 如果`Handler`中执行的是耗时的操作,在关闭`Activity`的时候停掉你的后台线程。线程停掉了,就相当于切断了`Handler`和外部连接的线,`Activity`自然会在合适的时候被回收。 
    - 如果`Handler`是被`delay`的`Message`持有了引用,那么在`Activity`的`onDestroy()`方法要调用`Handler`的`remove*`方法,把消息对象从消息队列移除就行了。 
            - 关于`Handler.remove*`方法
                        - `removeCallbacks(Runnable r)` ——清除r匹配上的Message。    
                        - `removeC4allbacks(Runnable r, Object token)` ——清除r匹配且匹配token(Message.obj)的Message,token为空时,只匹配r。
                        - `removeCallbacksAndMessages(Object token)` ——清除token匹配上的Message。
                        - `removeMessages(int what)` ——按what来匹配     
                        - `removeMessages(int what, Object object)` ——按what来匹配      
                        我们更多需要的是清除以该`Handler`为`target`的所有`Message(Callback)`就调用如下方法即可`handler.removeCallbacksAndMessages(null)`;
- 将`Handler`声明为静态类。
    静态类不持有外部类的对象,所以你的`Activity`可以随意被回收。但是不持有`Activity`的引用,如何去操作`Activity`中的一些对象? 这里要用到弱引用

public class MyActivity extends Activity {
        private MyHandler mHandler;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                mHandler = new MyHandler(this);
        }

        @Override
        protected void onDestroy() {
                // Remove all Runnable and Message.
                mHandler.removeCallbacksAndMessages(null);
                super.onDestroy();
        }

        static class MyHandler extends Handler {
                // WeakReference to the outer class's instance.
                private WeakReference<MyActivity> mOuter;

                public MyHandler(MyActivity activity) {
                        mOuter = new WeakReference<MyActivity>(activity);
                }

                @Override
                public void handleMessage(Message msg) {
                        MyActivity outer = mOuter.get();
                        if (outer != null) {
                                // Do something with outer as your wish.
                        }
                }
        }
}

 

本文为转载,看源处请移步:

http://www.eoeandroid.com/thread-332265-1-1.html

分享到:
评论

相关推荐

    Android Handler内存泄漏详解及其解决方案

    Handler 作为非静态内部类持有当前 Activity 的隐式引用,如果 Handler 没有被释放,其所持有的外部引用也就是 Activity 不可能被释放,导致内存泄漏。 Handler 内存泄漏的解决方法是使用静态内部类并继承 Handler...

    解决Android使用Handler造成内存泄露问题

    解决Handler导致内存泄露的方法有两种: 方法一:通过程序逻辑来进行保护。 1. 在关闭Activity的时候停掉你的后台线程。线程停掉了,就相当于切断了Handler和外部连接的线,Activity自然会在合适的时候被回收。 2....

    详解Android使用Handler造成内存泄露的分析及解决方法

    Android 中 Handler 造成内存泄露的分析及解决方法 什么是内存泄露? 在 Java 中,使用有向图机制,通过 GC 自动检查内存中的对象(什么时候检查由虚拟机决定),如果 GC 发现一个或一组对象为不可到达状态,则将...

    AndroidHandler内存泄漏详解及其解决方案.docx

    因为Handler持有Activity的引用,只要Handler还存在,Activity就不会被回收,从而导致内存泄漏。 **1.2 原理解释** 在Java中,非静态内部类和匿名内部类会隐式地持有外部类的引用。上述例子中的`Handler`就是一个...

    android内存泄露:4、Toast的错误使用导致内存泄露

    详细可参考博文:原创 android内存泄露:3、Handler的错误使用导致内存泄露 ,这篇文章我们将介绍:Toast的错误使用导致内存泄露 二、Toast的错误使用导致内存泄露 我们通常,连续点击按钮多次提示的 Toast,它...

    android性能优化之内存泄露

    异步线程中Handler的不当使用是导致内存泄露的常见原因。例如,Handler持有Activity的引用,但在Activity销毁后未能及时清除。 **解决策略**:确保Handler不持有Activity的强引用,可以使用WeakReference。 ##### ...

    Android 优化Handler防止内存泄露

    Handler 是 Android 中的一种机制,用于在不同的线程之间传递消息,但如果不正确地使用 Handler,可能会导致内存泄露。 在 Android 中,Handler 是一个很常用的机制,但它也很容易导致内存泄露。特别是在 Activity ...

    浅谈Android应用的内存优化及Handler的内存泄漏问题

    当对象不再使用时,如果不及时清理,可能会导致内存泄漏。内存泄漏是指无用的对象由于仍然有引用链指向它们,而无法被垃圾回收器(GC)回收。Android的Dalvik VM有一个内置的GC机制,用于定期回收不再使用的内存,但...

    Android handler message奇怪用法详解

    2. **弱引用与Handler**:使用WeakReference包裹Handler实例,防止Handler导致Activity或Fragment的内存泄漏,因为弱引用不会阻止对象被垃圾回收。 3. **自定义Message子类**:有时候,为了增强消息的可读性和可...

    Android Handler Looper

    在Android应用开发中,Handler、Looper和Message是实现线程间通信的重要机制,尤其是在...同时,需要注意的是,过度依赖Handler可能导致内存泄漏,因此在不再使用Handler时,记得及时移除引用,防止内存泄露的发生。

    android demo,使用Handler的postDelay,Runnable run实现延时3秒的splash。

    - 在SplashActivity的onDestroy或onPause方法中,调用`removeCallbacksAndMessages(null)`,以防止销毁活动时Runnable仍在后台运行,导致内存泄漏。 5. **注意事项**: - Splash Screen不宜过长,以免影响用户体验...

    android 中Handler 的几种写法

    当`Handler`被绑定到Activity或Fragment等生命周期有限的对象时,如果不正确处理,可能导致内存泄漏。使用`WeakReference`可以避免这种情况: ```java class MyHandler extends Handler { private WeakReference...

    Android内存泄漏案例分析

    在本次技术公开课中,讲师张权威将深入剖析Android平台下的内存泄漏案例,通过对一个具体案例的分析,展示内存泄漏的形成原因、诊断流程以及解决方案。 首先,案例中提到当连续多次打开应用时,界面出现卡顿,并且...

    android内存泄露测试

    - 使用`Dominator Tree`、`Package`等视图分析内存使用情况,查找可能导致内存泄露的对象。 #### 三、内存泄露的分析技巧 - **Dominator Tree Package**:通过查看包内对象的引用关系,寻找可能的内存泄露源头。 ...

    Android 内存 泄露 实践分析1

    7. **Service、BroadcastReceiver、ContentObserver、Handler和Thread**: 这些组件如果不正确关闭,可能导致内存泄露。 **解决策略** 1. **谨慎使用Context**: 了解Context的不同类型(Application、Activity等),...

    【Android开发入门】Android线程之Handler

    1. 避免内存泄漏:Handler的引用可能会导致Activity无法正常回收,因此在Activity的onDestroy()方法中应调用`removeCallbacksAndMessages(null)`,解除对Handler的引用。 2. 使用静态内部类的Handler:静态内部类...

    Android内存泄漏的八种可能.pdf

    如果 Handler 在 Activity 生命周期结束后没有被释放,可能会导致内存泄漏。 第六种可能:Thread 线程可能会导致内存泄漏,如果线程在 Activity 生命周期结束后没有被释放,可能会导致内存泄漏。 第七种可能:...

    【android】android之内存泄漏

    - 在静态成员中保存非静态成员的引用也会导致内存泄漏,因为静态成员的生命周期通常比非静态成员长得多。 4. **Bitmap对象管理不当**: - `Bitmap`对象占用大量内存,若不正确释放,很容易导致内存泄漏。 5. **...

    Handler对象中使用匿名内部类或非静态内部类正确地释放消息避免内存泄漏或增加Native内存

    然而,不当使用Handler,尤其是结合匿名内部类或非静态内部类,可能导致内存泄漏和Native内存增加,这对应用性能和稳定性造成负面影响。 首先,我们要理解内存泄漏的概念。内存泄漏是指程序中已分配的内存没有被...

Global site tag (gtag.js) - Google Analytics