檢測App內存泄露--LeakCanary工具
來自: http://blog.csdn.net/caroline_wendy/article/details/50580949
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.
</div>
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;
}
}</pre>
單例只應該做事務性的工作, 頁面操作應該使用回調, 不是引入控件. 本示例僅做為反面示例, 切勿學習.
</div>
3. 泄露內存
調用單例, 兩種引用都會導致內存泄露, 第一種是Context引用泄露, 第二種是子控件引用泄露. 避免方式是在onDestroy中, 清除引用.
最優方式:
在單例中只執行事務性工作, 不執行具體頁面操作, 可以使用接口回調, 異步處理.
</div>
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();
}
}</pre>
根據LeakCanary中的檢測結果, 修改內存泄露的地方, 就可以完美的解決問題.
內存泄露的問題對于應用的用戶體驗至關重要, 感謝Square的產品, 讓這件事變得如此簡單.
OK, that’s all! Enjoy it!
</div>
本文由用戶 luojia_lj 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!
相關經驗
相關資訊