AsyncTask造成的泄露
規(guī)范:所有AsyncTask必須是靜態(tài)的或者單獨的類牌芋, 絕對不允許非靜態(tài)內(nèi)部AsyncTask.
如果AsyncTask需要訪問外部的Activity或者M(jìn)odule, 在構(gòu)造函數(shù)中傳入這些參數(shù)野蝇, 然后使用WeakReference包裝晰赞。Handler, Runnable造成的泄露
規(guī)范:在Activity onDestroy中, 必須調(diào)用handler.removeCallbacksAndMessages(null)
對于AlertDialog纽甘, 其Listener必須使用DetachableClickListener包裝
public final class DetachableClickListener implements DialogInterface.OnClickListener {
public static DetachableClickListener wrap(DialogInterface.OnClickListener delegate) {
return new DetachableClickListener(delegate);
}
private DialogInterface.OnClickListener delegateOrNull;
private DetachableClickListener(DialogInterface.OnClickListener delegate) {
this.delegateOrNull = delegate;
}
@Override public void onClick(DialogInterface dialog, int which) {
if (delegateOrNull != null) {
delegateOrNull.onClick(dialog, which);
}
}
public void clearOnDetach(Dialog dialog) {
dialog.getWindow()
.getDecorView()
.getViewTreeObserver()
.addOnWindowAttachListener(new OnWindowAttachListener() {
@Override public void onWindowAttached() { }
@Override public void onWindowDetached() {
delegateOrNull = null;
}
});
}
}
DetachableClickListener clickListener = wrap(new DialogInterface.OnClickListener() {
@Override public void onClick(DialogInterface dialog, int which) {
MyActivity.this.makeCroissants();
}
});
//然后在使用的時候
AlertDialog dialog = new AlertDialog.Builder(this) //
.setPositiveButton("Baguette", clickListener) //
.create();
clickListener.clearOnDetach(dialog);
dialog.show();
HandlerThread造成的泄露
規(guī)范:可以有一個全局的BackgroudThread
不退出良蛮。
其余的HandlerThread在Activity銷毀的時候必須調(diào)用quit
或者quitSafely
方法單例持有Context
規(guī)范:單例如果要持有Context, 必須只能持有ApplicationContext.Bitmap使用不當(dāng)
規(guī)范:Bitmap使用完必須調(diào)用recycle, 并且手動置空View繪制不當(dāng)
規(guī)范:由于View繪制的時候會頻繁調(diào)用onDraw, 所以在onDraw中不能去生成Rect
,RectF
,Paint
等實例。共軛方法必須成對出現(xiàn)
比如在onResume中register悍赢,必須在onPause中unRegister所有Closeable對象必須close
包括但不局限于:File, InputStream, OutputStream等决瞳。不要跨線程置空
賦值在A線程, 則置空也必須在A線程左权。 除非我們有十二分的理由說不能在A線程置空皮胡。RxJava使用不當(dāng)
規(guī)范1:所有Subscription或者Disposable必須clear或者dispose
規(guī)范2:線程切換如果用到了Looper,必須在所有使用了非靜態(tài)內(nèi)部類的操作符之上使用onTerminateDetach操作符WebView造成的內(nèi)存泄露
規(guī)范1:WebView必須動態(tài)添加赏迟, 不要靜態(tài)添加
規(guī)范2:WebView最好使用單獨進(jìn)程
規(guī)范2:WebView銷毀必須按照如下格式
//先讓webviewJ下載空內(nèi)容
mWebView.loadDataWithBaseURL(null,"","text/html","utf-8",null);
//然后把webview從viewTree中移除
if(mWebView != null){
ViewGroup parent = (ViewGroup)mWebView.getParent();
if(parent != null){
parent.removeView(mWebView);
}
}
mWebView.stopLoading();
// 退出時調(diào)用此方法屡贺,移除綁定的服務(wù),否則某些特定系統(tǒng)會報錯 mWebView.getSettings().setJavaScriptEnabled(false); mWebView.clearHistory();
mWebView.clearView();
//移除webview中所有的view
mWebView.remvoeAllViews();
//銷毀webview
mWebView.destroy();
mWebView = null;
嚴(yán)禁static的View和Drawable.
不要依賴finalize方法進(jìn)行清理,finalize是救命稻草甩栈,但不一定能救命
finalize方法去執(zhí)行清理泻仙,JVM只保證finalize方法最多被執(zhí)行一次, 也就是說finalize方法可能一次都不會被執(zhí)行量没。
JVM會把實現(xiàn)了finalize方法的對象包裝成FinalizerReference玉转, 然后放到一個雙向隊列中, 當(dāng)gc線程工作工作的時候殴蹄,不斷取出該隊列的元素究抓, 然后執(zhí)行finalize方法, 也就是說finalize方法不是在主線程中執(zhí)行的袭灯。創(chuàng)建的時候先創(chuàng)建父類漩蟆, 銷毀的時候先銷毀自己。
也就是說在onCreate中先調(diào)用super.onCreate()
, 然后在做自己的事情
在onDestroy的時候妓蛮, 先銷毀自己持有的引用怠李, 然后在super.onDestroy()
在onDestroy中銷毀屬性動畫(理論上應(yīng)該銷毀一切動畫)
盡量不要在非靜態(tài)內(nèi)部類中持有外部類的屬性,因為在非靜態(tài)內(nèi)部類中蛤克, 會把所有用到的外部類的屬性作為自己的屬性給保存起來捺癞, 一般情況下這沒有什么問題, 但是一旦非靜態(tài)內(nèi)部類存活時間比外部類存活時間長构挤, 就容易出現(xiàn)問題