Bootstrap

内存泄漏案例分享2-Fragment的内存泄漏

案例2——hprof文件显示出Fragment内存泄漏

接下来我们来看fragment内存泄漏,老规矩查看fields和references,确保它符合内存泄漏的情形;我们点击jump to source查看泄漏的位置

在这里插入图片描述

Fragment#MZBannerView#内部类Runnbale

/**
 * Banner 切换时间间隔
 */
private int mDelayedTime = 5000;
private final Runnable mLoopRunnable = new Runnable() {
       @Override
       public void run() {
           if (mIsAutoPlay) {
                mCurrentItem = mViewPager.getCurrentItem();
                mCurrentItem++;
               if (mCurrentItem > mAdapter.getCount() - 1) {
                    mCurrentItem = 0;
                    mViewPager.setCurrentItem(mCurrentItem, false);
                    mHandler.postDelayed(this, mDelayedTime);
               } else {
                    mViewPager.setCurrentItem(mCurrentItem);
                    mHandler.postDelayed(this, mDelayedTime);
               }
           } else {
                mHandler.postDelayed(this, mDelayedTime);
           }
       }
   };

可以看到Fragment内存泄漏的第一个原因,内部类runnable持有了view的实例,每个Runnbale会发送一个延时5秒的消息,消息发送期间,有可能view、fragment已经结束了生命周期,此时产生了内存泄漏。
解决办法也很简单,view离开窗口的时候,释放Handler中消息,释放Runnbale对view 的引用。

  1. 静态Runnbale内部类+对view的弱引用(此部分代码与前面的示例很相似,不重复贴代码了)
  2. 离开窗口remove#handler消息
    view对Activity暴露了pause方法,在Activity销毁时,强制清空handler的任务;
// view代码
/**
   * 停止轮播
    */
   public void pause() {
        mIsAutoPlay = false;
        mHandler.removeCallbacks(mLoopRunnable);
        mBannerPageClickListener = null;
   }
// Activity代码:
    @Override
   public void onDestroy() {
       super.onDestroy();
        dataBing.homeBanner.pause();
   }
;