-
AsyncTask造成的泄露
规范:所有AsyncTask必须是静态的或者单独的类, 绝对不允许非静态内部AsyncTask.
如果AsyncTask需要访问外部的Activity或者Module, 在构造函数中传入这些参数, 然后使用WeakReference包装。 -
Handler, Runnable造成的泄露
规范:在Activity onDestroy中, 必须调用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造成的泄露
规范:可以有一个全局的BackgroudThread
不退出。
其余的HandlerThread在Activity销毁的时候必须调用quit
或者quitSafely
方法 -
单例持有Context
规范:单例如果要持有Context, 必须只能持有ApplicationContext. -
Bitmap使用不当
规范:Bitmap使用完必须调用recycle, 并且手动置空 -
View绘制不当
规范:由于View绘制的时候会频繁调用onDraw, 所以在onDraw中不能去生成Rect
,RectF
,Paint
等实例。 -
共轭方法必须成对出现
比如在onResume中register,必须在onPause中unRegister -
所有Closeable对象必须close
包括但不局限于:File, InputStream, OutputStream等。 -
不要跨线程置空
赋值在A线程, 则置空也必须在A线程。 除非我们有十二分的理由说不能在A线程置空。 -
RxJava使用不当
规范1:所有Subscription或者Disposable必须clear或者dispose
规范2:线程切换如果用到了Looper,必须在所有使用了非静态内部类的操作符之上使用onTerminateDetach操作符 -
WebView造成的内存泄露
规范1:WebView必须动态添加, 不要静态添加
规范2:WebView最好使用单独进程
规范2:WebView销毁必须按照如下格式
//先让webviewJ下载空内容
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();
// 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错 mWebView.getSettings().setJavaScriptEnabled(false); mWebView.clearHistory();
mWebView.clearView();
//移除webview中所有的view
mWebView.remvoeAllViews();
//销毁webview
mWebView.destroy();
mWebView = null;
-
严禁static的View和Drawable.
-
不要依赖finalize方法进行清理,finalize是救命稻草,但不一定能救命
finalize方法去执行清理,JVM只保证finalize方法最多被执行一次, 也就是说finalize方法可能一次都不会被执行。
JVM会把实现了finalize方法的对象包装成FinalizerReference, 然后放到一个双向队列中, 当gc线程工作工作的时候,不断取出该队列的元素, 然后执行finalize方法, 也就是说finalize方法不是在主线程中执行的。 -
创建的时候先创建父类, 销毁的时候先销毁自己。
也就是说在onCreate中先调用super.onCreate()
, 然后在做自己的事情
在onDestroy的时候, 先销毁自己持有的引用, 然后在super.onDestroy()
-
在onDestroy中销毁属性动画(理论上应该销毁一切动画)
-
尽量不要在非静态内部类中持有外部类的属性,因为在非静态内部类中, 会把所有用到的外部类的属性作为自己的属性给保存起来, 一般情况下这没有什么问题, 但是一旦非静态内部类存活时间比外部类存活时间长, 就容易出现问题
网友评论