关联文章:

Android OOM 分析

Android异步消息处理线程之----Looper+MessageQueue+Handler

Android 中Handler

Android HandlerThread

Handler sendMessage 与 obtainMessage (sendToTarget)比较

 

前言:

对于Handler 在android 系统引起的内存泄漏,网上已经有了很多优秀的博文,我这边也是参考了它们并结合自己的经验进行总结,希望利己利人。

 

举例说明:

在java中非静态内部类和匿名内部类都会隐式持有当前类的外部引用,由于Handler是非静态内部类所以其持有当前Activity的隐式引用,如果Handler没有被释放,其所持有的外部引用也就是Activity也不可能被释放,当一个对象一句不需要再使用了,本来该被回收时,而有另外一个正在使用的对象持有它的引用从而导致它不能被回收,这导致本该被回收的对象不能被回收而停留在堆内存中,这就产生了内存泄漏,并最终造成了OOM。

来看下例子:

public class MainActivity extends Activity {    private int[] array = new int[1024 * 1024];    private Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);        }    };    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        mHandler.postDelayed(new Runnable() {            @Override            public void run() {                //            }        }, 1000 * 60 * 5);    }}

代码中:

  • 申请一个大概4M 的数组空间
  • Handler 会延迟5分钟post

 

问题验证:

经过几次back 退出应用之后,来看下内存情况:

这个时候即使是一直GC,也无法回收mem,再来一次操作后:

再次多出4M左右的空间,GC还是无法回收

 

解决办法:

解决这个问题思路就是使用静态内部类并继承Handler时(或者也可以单独存放成一个类文件)。因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露。当你需要在静态内部类中调用外部的Activity时,我们可以使用弱引用来处理。另外关于同样也需要将Runnable设置为静态的成员属性。修改后不会导致内存泄露的代码如下:

public class MainActivity extends Activity {    private int[] array = new int[1024 * 1024];    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        actionTo();    }            private static class MyHandler extends Handler {        private final WeakReference mActivity;        public MyHandler(Activity activity) {            mActivity = new WeakReference(activity);        }                @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);        }    }        private static final Runnable mRunnable = new Runnable() {        @Override        public void run() {            //        }    };        private void actionTo() {        MyHandler mHandler = new MyHandler(this);        mHandler.postDelayed(mRunnable, 1000 * 60 * 5);    }}

 

 

其他更多关于泄漏的case 可以看下 Android OOM 分析

 

 

更多相关文章

  1. Nginx系列教程(四)| 一文带你读懂Nginx的动静分离
  2. Android(安卓)Studio优化内存配置
  3. Android(安卓)Runnable运行在哪个线程
  4. Handler内存泄露原理及解决方法
  5. LeanCanary——消除Android中的内存泄露
  6. Android(安卓)Studio 设置内存大小及原理
  7. android静态注册的广播在某些手机上无法正常接收
  8. Android(安卓)内存泄漏检测
  9. Android实现动态高斯模糊

随机推荐

  1. Android电话功能各部分深入探讨
  2. android studio学习日记
  3. android保存文件到手机内存
  4. Android(安卓)判断网络是否可用 & 获取IP
  5. android定位的实现
  6. mac下下载安装Android Studio教程
  7. Android下调用传感器
  8. Android 数据保存
  9. Android开发现状分析(2020版)
  10. Android--布局方式(LinearLayout)学习