1 内存泄漏的场景
1.1 单例持有了Activity的context的引用
改为单例持有applicationContext对象的引用。
1.2内部非静态类持有了类的实例引用
使用内部静态类。
1.3 Handler造成内存泄漏
将Handler声明为静态的内部类 继承Handler
通过弱引用的方式引入Activity
private HandlermHandler;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mHandler =new MyHandler(this);
}
private static class MyHandlerextends Handler {
private final WeakReferencemActivity;
public MyHandler(Activity activity) {
mActivity =new WeakReference(activity);
}
@Override
public void handleMessage(Message msg) {
if (mActivity.get() ==null) {
LoginActivity instance = (LoginActivity)mActivity.get();
int event = msg.arg1;
int result = msg.arg2;
Object data = msg.obj;
}
}
}
1.4线程造成内存泄漏
将自定义的AsncTask和Runnable类定义成静态的内部类
可以调用AsncTask.cancel()结束任务
private static class MyRunnable implements Runnable{
@Override public void run() { }
}
1.5 WebView引起内存泄漏
加载的页面非常复杂,或包含很多图片,会占用很多的内存。
将WebView所处的类放在单独的进程中,必要的时候调用killProcess杀掉这个进程,以便占用的内存被回收。
@Override
protected void onDestroy() {
destroyWebView();
android.os.Process.killProcess(android.os.Process.myPid());
super.onDestroy();
}
private void destroyWebView() {
if (mWebView != null) {
mWebView.pauseTimers();
mWebView.removeAllViews();
mWebView.destroy();
mWebView = null;
}
}
2 内存优化框架
WeakReference、ReferenceQueue Dump出heap信息,分析出泄漏路径。
引用类型:
StrongReference
SoftReference(内存空间不够了,垃圾回收器才回收)
WeakReference(生命周期更短,垃圾回收器扫描到进行标记,下一次立即回收)
虚引用跟没有引用是一样的,垃圾回收器在任何情况下可以回收它
ReferenceQueue和 SoftReference、WeakReference联合使用
Leakcanary的使用
配置build.gradle:
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.2'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.2'
}
public class LeakApplication extends Application {
private RefWatcher refWatcher;
@Override
public void onCreate() {
super.onCreate();
refWatcher= setupLeakCanary();
}
private RefWatcher setupLeakCanary() {
if (LeakCanary.isInAnalyzerProcess(this)) {
return RefWatcher.DISABLED;
}
return LeakCanary.install(this);
}
public static RefWatcher getRefWatcher(Context context) {
LeakApplication leakApplication = (LeakApplication) context.getApplicationContext();
return leakApplication.refWatcher;
}
}
测试:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LeakThread leakThread = new LeakThread();
leakThread.start();
}
class LeakThread extends Thread {
@Override
public void run() {
try {
Thread.sleep(6 * 60 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
RefWatcher refWatcher = LeakApplication.getRefWatcher(this);
refWatcher.watch(this);
}
}