Handler造成Activity泄漏,用弱引用真的有用么?

网上很多教程,解决Handler造成的内存泄漏问题,基本上是使用弱引用来解决的,但是使用弱引用真的有效么?直接写代码演示,以及分析。

  • 下面分析过程分为4种,第一种是Handler声明成静态的并且弱引用Activity。第二种是handler声明成成员变量的,使用弱引用。第三种是将handler声明成静态的。第四种是声明成普通成员变量,但是在onDestory中移除未执行完的任务。

    • 第一种 Handler声明成静态的并且弱引用Activity
    • 下面是代码

      `   public static   class UIHndler extends android.os.Handler{
      WeakReference<MainActivity> softReference;
      public UIHndler(MainActivity mainActivity){
          softReference=new WeakReference<MainActivity>(mainActivity);
      }
      
      @Override
      public void handleMessage(Message msg) {
          super.handleMessage(msg);
          MainActivity mainActivity = softReference.get();
          if(mainActivity!=null){
              // 更新ui
              mainActivity.handler();
          }
      }
      }`
      
    • 这种是我们经常写的代码,也是网上很多教程这样写的
    • 下面是执行前和执行后的效果图,我们横竖屏切换来完成这个操作。
    • 这张图是Activity启动的图
    • 可以看到,初始申请内存是3.6m左右。接下来 我们反复的横竖屏切换,拿到下图
    • 发现内存没有太多,接下来我们运行下GC,看到下图
    • 发下确实没有造成内存泄漏,但是这样能说是弱引用的原因么?因为我们的Handler声明成静态的了
  • 接下来我们演示第二种情况。handler声明成成员变量的,使用弱引用

    • 下面是代码

        public    class UIHndler extends android.os.Handler{
          WeakReference<MainActivity> softReference;
          public UIHndler(MainActivity mainActivity){
              softReference=new WeakReference<MainActivity>(mainActivity);
          }
      
      @Override
      public void handleMessage(Message msg) {
          super.handleMessage(msg);
          MainActivity mainActivity = softReference.get();
          if(mainActivity!=null){
              // 更新ui
              mainActivity.handler();
          }
      }
      }
      
    • 接下来我们还是横竖屏切换,看看内存申请


* 接下来我们Gc


* 发现内存并没有少,这是因为在 hanlder中有延迟任务。那么等延迟任务执行完了之后我们在GC下。下图等延迟任务执行万之后的是GC效果

  • 发现也没有造成内存泄漏,但是得等到handler中的任务都执行完成之后才会清除内存。这样的话性能还是比较低,当然也没有造成内存泄漏。

    • 接下来演示第三种情况 将handler声明成静态的
  • 下面是我们的代码

    public static android.os.Handler handler=new android.os.Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            tv.setText("dsa");
        }
    }; 
    
  • 也是反复的横竖屏切换

  • 接下来gc

  • 发现只要handler声明称static的就不会造成内存泄漏,而且回收很快

那么通过上面的三种情况我们发现。只要是handler声明成static就不会造成内存泄漏,声明成弱引用activity的话,虽然也不会造成内存泄漏,但是需要等到handler中没有执行的任务后才会回收,因此性能不高。

handler之所以造成内存泄漏是因为在activity销毁的时候,handler中有未执行完的任务。那么接下来我们在Activity销毁的时候清空handelr没有执行的任务会是什么效果

  • 接下来我们看第四种情况

    • handler代码如下

          public static android.os.Handler handler=new android.os.Handler(){
          @Override
          public void handleMessage(Message msg) {
              super.handleMessage(msg);
              tv.setText("dsa");
          }
      };  
      
    • 但是我们在activity的onDestory中添加了如下代码,清空所有handler中没有执行完的任务

         protected void onDestroy() {
          super.onDestroy();
          handler.removeCallbacksAndMessages(null);
      }
      
    • 下面是反复横竖屏内存图

  • 下面是GC之后的
  • 发现也没有内存泄漏

总结

  • handler造成内存泄漏是因为在Activity销毁的时候还有未执行完的任务
  • 静态static可以解决内存泄漏
  • 使用弱引用也可以解决内存泄漏,但是需要等到handler的中任务都执行完,才会释放activity内存,不如直接static释放的快
  • handler造成内存泄漏有 两种方案:一种是业务逻辑上,在activity销毁的时候移除所有未执行的任务。一种是从GC上,通过static的Handler或者弱引用解决。但是单独的使用弱引用性能不是太高。
  • 欢迎吐槽 QQ2205790462
发布了33 篇原创文章 · 获赞 21 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u013356254/article/details/52463636