关于android中内存泄漏的几种情况

先做个标记,挖个坑,以后来填。

参考的是大佬的博客: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。

原文地址:https://www.cnblogs.com/hankzhouAndroid/p/8735024.html