• 关于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。

  • 相关阅读:
    Thinking in java Chapter10 内部类
    策略设计模式 Strategy模式
    Thinking in java Chapter9 接口
    Thinking in java Chapter8 多态
    Thinking in java Chapter7 复用类
    mock服务
    文件的使用方式
    字符编码与文件处理方式
    各容器类型及内置方法
    python各数据类型及内置方式:
  • 原文地址:https://www.cnblogs.com/hankzhouAndroid/p/8735024.html
Copyright © 2020-2023  润新知