检测App内存泄露--LeakCanary工具
2016-01-25 16:08
260 查看
欢迎Follow我的GitHub, 关注我的CSDN.
LeakCanary是检测App内存泄露的工具, 内存泄露是Android开发中常见的问题, 使用程序的稳定性下降.
本文示例的Github下载地址.
![](https://img-blog.csdn.net/20160125160731928)
主要原因:
生命周期较长的类使用Activity的Context, 导致Activity被引用, 无法被及时回收. 解决方法, 除了需要页面支持类, 如Dialog等, 全部使用应用的Context, 即Context.getApplicationContext().
LeakCanary可以检查出页面的泄露问题, 并提供具体位置.
![](https://img-blog.csdn.net/20160125160752332)
表明: LeakSingle的静态单例sInstance引用LeakSingle的mContext, 导致MainActivity的instance泄露.
我来讲解一下如何使用吧.
引入应用
配置非常简单, 会增加一个附属应用, 去掉Application的引用, 就可以移除LeakCanary.
单例只应该做事务性的工作, 页面操作应该使用回调, 不是引入控件. 本示例仅做为反面示例, 切勿学习.
最优方式:
在单例中只执行事务性工作, 不执行具体页面操作, 可以使用接口回调, 异步处理.
根据LeakCanary中的检测结果, 修改内存泄露的地方, 就可以完美的解决问题.
内存泄露的问题对于应用的用户体验至关重要, 感谢Square的产品, 让这件事变得如此简单.
OK, that’s all! Enjoy it!
LeakCanary是检测App内存泄露的工具, 内存泄露是Android开发中常见的问题, 使用程序的稳定性下降.
本文示例的Github下载地址.
主要原因:
生命周期较长的类使用Activity的Context, 导致Activity被引用, 无法被及时回收. 解决方法, 除了需要页面支持类, 如Dialog等, 全部使用应用的Context, 即Context.getApplicationContext().
LeakCanary可以检查出页面的泄露问题, 并提供具体位置.
表明: LeakSingle的静态单例sInstance引用LeakSingle的mContext, 导致MainActivity的instance泄露.
我来讲解一下如何使用吧.
1. 依赖和引入
build.gradle的依赖.debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' // or 1.4-beta1 releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1 testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1
引入应用
public class DemoApplication extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); } }
配置非常简单, 会增加一个附属应用, 去掉Application的引用, 就可以移除LeakCanary.
2. 泄露单例
泄露单例, 引入页面的TextView, 强制保留的父Activity, 会导致内存泄露, 可以在onDestroy时, 解引用避免./** * 泄露单例, 设计混乱, 单例只应该做事务性的工作, 页面操作应该使用回调. * 本示例仅做为反面示例, 切勿学习. * <p/> * Created by wangchenlong on 16/1/25. */ public class LeakSingle { private Context mContext; private TextView mTextView; private static LeakSingle sInstance; private LeakSingle(Context context) { mContext = context; } public static LeakSingle getInstance(Context context) { if (sInstance == null) { sInstance = new LeakSingle(context); } return sInstance; } // 内存泄露 public void setRetainedTextView(TextView tv) { mTextView = tv; mTextView.setText(mContext.getString(R.string.app_name)); } // 删除引用, 防止泄露 public void removeRetainedTextView() { mTextView = null; } }
单例只应该做事务性的工作, 页面操作应该使用回调, 不是引入控件. 本示例仅做为反面示例, 切勿学习.
3. 泄露内存
调用单例, 两种引用都会导致内存泄露, 第一种是Context引用泄露, 第二种是子控件引用泄露. 避免方式是在onDestroy中, 清除引用.最优方式:
在单例中只执行事务性工作, 不执行具体页面操作, 可以使用接口回调, 异步处理.
public class MainActivity extends AppCompatActivity { @Bind(R.id.main_tv_text) TextView mTvText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); /** * me.chunyu.spike.wcl_leakcanary_demo.MainActivity has leaked: * GC ROOT static me.chunyu.spike.wcl_leakcanary_demo.LeakSingle.sInstance * references me.chunyu.spike.wcl_leakcanary_demo.LeakSingle.mContext * leaks me.chunyu.spike.wcl_leakcanary_demo.MainActivity instance */ // LeakSingle.getInstance(this).setRetainedTextView(mTvText); /** * me.chunyu.spike.wcl_leakcanary_demo.MainActivity has leaked: * GC ROOT static me.chunyu.spike.wcl_leakcanary_demo.LeakSingle.sInstance * references me.chunyu.spike.wcl_leakcanary_demo.LeakSingle.mTextView * references android.support.v7.widget.AppCompatTextView.mContext * leaks me.chunyu.spike.wcl_leakcanary_demo.MainActivity instance */ LeakSingle.getInstance(this.getApplication()).setRetainedTextView(mTvText); } @Override protected void onDestroy() { super.onDestroy(); // 防止内泄露 LeakSingle.getInstance(this.getApplication()).removeRetainedTextView(); } }
根据LeakCanary中的检测结果, 修改内存泄露的地方, 就可以完美的解决问题.
内存泄露的问题对于应用的用户体验至关重要, 感谢Square的产品, 让这件事变得如此简单.
OK, that’s all! Enjoy it!
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories