Android内存泄漏及内存优化框架

作者:陆金龙    发表时间:2024-02-25 04:49   

关键词:  

1.内存泄漏的场景

1.1 单例持有了Activity的context的引用
改为单例持有applicationContext对象的引用。

1.2 内部非静态类持有了类的实例引用

使用内部静态类。

1.3 Handler造成内存泄漏

将Handler声明为静态的内部类 继承Handler

通过弱引用的方式引入Activity

private Handler mHandler;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    mHandler = new MyHandler(this);
}
private static class MyHandler extends Handler {
    private final WeakReference<Activity> mActivity;
    public MyHandler(Activity activity) {
        mActivity = new WeakReference<Activity>(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的使用

配置app工程的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);

}

}