今天做项目时遇到内存泄漏,经过多番研究,终于解决与大家分享。
因为我的MainActivity中使用了viewpage+Fragment,然后在Fragment使用handler+Message导致了内存泄漏。
原因:
在java中,创建一个非静态的内部类实例,就会引用它的外围实例。如果这个非静态内部类实例做了一些耗时的操作,就会造成外围对象不会被回收,从而导致内存泄漏。也就是说,Handler 为匿名内部类实例,会引用外围对象(handleMessage方法中可以直接调用Activity的方法),如果该Handler在Activity调用onDestroy()方法退出时依然还有消息需要处理,那么这个Activity就不会被回收。
解决方法:
1.在对应的Fragment下,将内部类变成静态内部类
2.如果有强引用Activity中的属性,则将该属性的引用方式改为弱引用。
3.在业务允许的情况下,当Activity执行onDestory时,结束这些耗时任务。
/**
* 初始化MyAppFragmentHandler
*/
private MyAppFragmentHandler handler = new MyAppFragmentHandler(this);
/**
* 将内部类变成静态内部类
*/
private static class MyAppFragmentHandler extends Handler {
//第二步,将需要引用Activity的地方,改成弱引用。
private WeakReference<MyAppFragment> weakReference;
public MyAppFragmentHandler(MyAppFragment fragment) {
weakReference = new WeakReference<>(fragment);
}
@Override
public void handleMessage(Message msg) {
MyAppFragment fragment = weakReference.get();
//如果Fragment所在的Activity被释放回收了,则不处理这些消息
if (fragment == null)
return;
if (fragment.getActivity() == null)
return;
if (fragment.getActivity().isFinishing())
return;
switch (msg.what) {
case Constant.MSG.APP_OK:
//收到消息进行处理
break;
}
}
}
经过多方面的了解,即使是在Activity内使用handler+Message导致了也会造成内存泄漏。
解决思路和以上相同。
代码如下:
/**
* 初始化MainActivityHandler
*/
public MainActivityHandler mainActivityHandler = new MainActivityHandler(this);
/**
* 防止因为使用handler造成内存泄漏
*/
//第一步,将Handler改成静态内部类。
private static class MainActivityHandler extends Handler {
//第二步,将需要引用Activity的地方,改成弱引用。
private WeakReference<MainActivity> weakReference;
public MainActivityHandler(MainActivity activity) {
weakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity mainActivity = weakReference.get();
//如果Activity被释放回收了,则不处理这些消息
if (mainActivity == null || mainActivity.isFinishing())
return;
switch (msg.what) {
case UPDATE_VERSION:
//收到消息后进行后续处理
break;
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
//在业务允许的情况下,结束这些耗时任务。
handler.removeCallbacksAndMessages(null);
}