先做个标记,挖个坑,以后来填。
参考的是大佬的博客:https://www.jianshu.com/p/ab4a7e353076.
其实看了大佬的文章,我就看到了一句话:
类A有一个成员变量B,如果B的生命周期比A长,那么在A想要回收的时候,发现B仍然持有A的引用。就会导致A无法回收,从而内存泄漏。
当然大佬们帮我列举出了各种各样可能的情况,但是万变不离其宗。
简单说吧,如果类成员的命比类实例还要长,那就要看好了,说不定就泄漏了。
解决的方式无非也就是-让类的成员的命,比类实例短,或者一致。
大佬列举出的方案是,使用静态内部类+弱引用,可以很好地避免内存泄漏。
1) 就在我们常规使用Handler的时候,也有可能会出现内存泄漏的情况。 因为,创建handler对象的时候,handler会持有当前activity的引用。
而 当前activity的生命周期 和 handler执行handlerMessage其实是两个独立的过程。
如果在某一个handlerMessage执行的时候,activity被执行了finish将要被回收,那handler所持有的activity引用,就会阻止activity的回收,造成泄漏。
这种情况的解决方法,就是 在创建handler的时候,使用静态内部类+activity弱引用的方式。(弱引用:当所持有的引用对象想要被释放时,不会阻止其释放,如果handler持有activity的弱引用,那么当activity被回收时,弱引用并不会阻止它回收,但是这么做也有一个后果,就是如果handlerMessage执行到一半,发现activity没了,那么后续的执行过程,也有可能就终止)
public class MainActivity extends AppCompatActivity {
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new MyHandler(this);
start();
}
private void start() {
Message msg = Message.obtain();
msg.what = 1;
mHandler.sendMessage(msg);
}
private static class MyHandler extends Handler {//用静态内部类的方式来写handler,
private WeakReference<MainActivity> activityWeakReference;//并且用activity
public MyHandler(MainActivity activity) {
activityWeakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = activityWeakReference.get();
if (activity != null) {
if (msg.what == 1) {
// 做相应逻辑
}
}
}
}
}
Timer和TimerTask 也有可能造成泄漏,原因,和上面提到的handler一样。 如果activity要被回收了,但是timerTask还在执行(还持有activity的引用),那么activity也无法正常回收。 处理方式,在适当的时候,将timer和timerTask先于activity释放。
2)静态成员变量引起内存泄漏:
静态成员变量所处的位置并不是堆,而是单独在一个静态池。静态池的生命周期和application一样长,是要比activity要长的。所以,当activity中有一个静态成员变量,它持有activity的引用时,在activity将要被回收,而静态成员变量持有activity引用导致无法回收,则造成泄漏。
解决方法,在适当的时候,让将静态成员变量设置为null,让它不再持有activity的引用。
3)集合中的 对象未清理,导致内存泄漏:
常见的一个情况:如果一个你自定义了一个MyActivityManager.java,想用一个ArrayList来管理所有的Activity,事实上,所有的activity在实例化之后,都会被add到ArrayList中,这个ArrayList就会持有所有activity的引用。
当,某个activity被回收之后,如果arrayList没有及时将该activity从集合中remove,也会阻止activity的回收。
处理方式:在Activity的onDestroy方法里面,调用MyActivityManager.remove(this);来将自身remove掉。
4)资源未释放或者未关闭:
常见的是IO流,使用之后必须及时关闭,因为他们会占用缓存区的内存空间。如果不释放,就会一直占用。
5)属性动画
如果在activity中启动了属性动画(ObjectAnimator),但是在activity销毁的时候没有cancel掉动画。那么,虽然activity不可见了,但是属性动画依然会一直不停地执行下去,只是你看不到。
这种时候,ObjectAnimator所处的控件会持有activity的引用,也会导致activity无法回收。
6)webView
webView也会造成内存泄漏,但是由于WebView我没有使用过,所以不多说了。
总结出来,要避免内存泄漏:
构造单例的时候,如果一定要使用Context,别用Activity.context,而是用Activity.context.getApplicationContext();
如果要构造一个绝对安全的handler,记得使用静态内部类+弱引用。 或者在Activity销毁之前,确保handler的所有handlerMessage都执行终止。
Timer,timerTask,属性动画,在activity销毁时,记得cancel或者释放。
IO流 在Activity销毁之前,一定要close。
在activity销毁之前,一定要先移除掉WebView。