Android Handler使用导致内存溢出附带LeakCanary排查
来源:互联网 发布:图像分割算法代码 编辑:程序博客网 时间:2024/05/29 11:14
最近项目马上结束了在对项目进行检查有没有内存泄漏的地方,这里使用的是leakcanary。
使用步骤很简单:
- 添加依赖:
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
} - 配置Application
public class ExampleApplication extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); }}
这都是github上的网址:https://github.com/square/leakcanary
下面是检测出来的结果。
这是一个提醒框,提醒用户正在加载中。仔细查看了下代码能导致内存溢出的只有这一行代码。
public LoadingDialog getDialog(String info) { Builder b = new Builder(mContext); b.setInfo(info); dialog = b.create(); dialog.show(); UIUtils.postDelayed(new Runnable() { @Override public void run() { if (dialog.isShowing()) { dialog.dismiss(); MlsApplication.showToast("操作超时,请稍后再试"); } } }, 10000); return dialog; }
这里是调用的Handler中的postDelayed()方法延时执行某个动作。
这里有这样一层关系Dialog创建时的参数有Activity的Context所以dialog中有context的引用,又因为handler持有外部类的引用为什么持有呢摘抄一段话:
- 当一个Android应用启动时,框架会分配到一个Looper实例给应用的主线程。这个Looper的主要工作就是处理一个接着一个的消息对象。在Android中,所有Android框架的事件(比如Activity的生命周期方法的调用和按钮的点击等)都是放到消息中,然后加入到Looper要处理的消息队列中,由Looper依次处理。主线程的Looper的生命周期和应用的一样长。
- 当在主线程中初始化一个Handler时,它就会关联到Looper的消息队列。发送到消息队列的消息本身就持有Handler的引用,只有这样Looper在处理这个条消息的时候才能调用Handler#handleMessage(Message)处理消息。
- 在Java中,非静态的内部类和匿名内部类都会隐式地持有其外部类的引用。而静态的内部类则不会。
链接:http://johnnyshieh.github.io/android/2015/09/03/android-handler-memory-leak/
其中runnable使用的是匿名内部类也持有外部类的引用,这就引发了一个问题当Activity finish的时候因为还有其他类对Activity持有引用就不会导致Activity从内存中销毁最后就会引发内存泄漏。
下面是解决办法:
因为静态类是不会持有外部类的引用,但是会有一个问题?怎么在静态内部类中使用外部类的变量呢?这里就要使用弱引用WeakReference.
1.首先创建一个静态的handler
private static class MyHandler extends Handler { private final WeakReference<Context> mActivity; private MyHandler(Context mActivity) { this.mActivity = new WeakReference(mActivity); } }
2.创建一个静态的Runnable
private static final class WeakRunnable implements Runnable { private WeakReference<Dialog> dialog; public WeakRunnable(Dialog dialog) { this.dialog =new WeakReference < Dialog > (dialog); } @Override public void run() { Dialog dialog = this.dialog.get(); if (null != dialog && dialog.isShowing()) { dialog.dismiss(); } } }
3.修改调用
handler.postDelayed(new WeakRunnable(dialog), 100000);
这样在重新运行程序连续切换界面旋转屏幕都不会出现内存泄漏了。
0 0
- Android Handler使用导致内存溢出附带LeakCanary排查
- LeakCanary 内存溢出检测工具
- LeakCanary-------快速简单排查Android中的内存泄露
- Android内存溢出与优化(四)——防止Handler导致的内存泄露
- JceSecurity/BouncyCastleProvider导致JVM内存溢出、CPU过高问题排查
- JVM内存溢出导致的CPU过高问题排查案例
- Android使用bitmap导致内存溢出(oom)问题
- Android中Handler使用不当导致内存泄露的问题
- android 使用Handler 会导致内存泄漏问题
- 内存溢出排查
- 内存溢出排查步骤:
- Android 使用LeakCanary 检测内存泄露
- Android 使用LeakCanary 检测内存泄露
- Android 使用LeakCanary 检测内存泄露
- Android 使用LeakCanary 检测内存泄露
- 使用leakcanary检测Android项目内存泄露
- 不会内存溢出的Android Handler写法
- Android多线程Handler内存溢出问题
- SAP中查看account登陆次数及时间的情况
- 数据绑定库Data Binding的使用
- HDU2511 汉诺塔10
- 金融路演产品的几点理解
- 学习笔记一:HotSpot中的一些概念
- Android Handler使用导致内存溢出附带LeakCanary排查
- PHP简介
- 148.Sort List
- 菜鸟成长记-runtime历程
- openssh的密钥登录 无密码登录
- maven 编译命令
- tomcat部署maven项目缺少spring-web.xxx.jar
- JavaBean中DAO设计模式介绍
- <s:if>标签和<c:if>标签的一点区别