阅读 130

Butter Knife在项目中的一个小坑(解绑部分)

结论:

Butter Knife在进行unbind()操作的时候会把页面的view引用置空。要注意一下

过程

今天项目在调试的时候突然报了一个错

(请忽略包名)
01-20 21:35:18.737 29857-30181/com.amplitude.tron.volksradio22 E/Adreno-GSL: <gsl_memory_alloc_pure:1971>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.
01-20 21:35:18.737 29857-30181/com.amplitude.tron.volksradio22 W/Adreno-GSL: <gsl_ldd_control:475>: ioctl fd 27 code 0x40080921 (IOCTL_KGSL_SHAREDMEM_FREE) failed: errno 22 Invalid argument
01-20 21:35:18.746 29857-30181/com.amplitude.tron.volksradio22 W/Adreno-GSL: <sharedmem_gpumem_alloc_id:2260>: sharedmem_gpumem_alloc: mmap failed errno 12 Out of memory
01-20 21:35:18.748 29857-30181/com.amplitude.tron.volksradio22 E/Adreno-GSL: <gsl_memory_alloc_pure:1971>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.
01-20 21:35:18.757 29857-30181/com.amplitude.tron.volksradio22 W/Adreno-GSL: <sharedmem_gpumem_alloc_id:2260>: sharedmem_gpumem_alloc: mmap failed errno 12 Out of memory
01-20 21:35:18.759 29857-30181/com.amplitude.tron.volksradio22 E/Adreno-GSL: <gsl_memory_alloc_pure:1971>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.
01-20 21:35:18.768 29857-30181/com.amplitude.tron.volksradio22 W/Adreno-GSL: <sharedmem_gpumem_alloc_id:2260>: sharedmem_gpumem_alloc: mmap failed errno 12 Out of memory
01-20 21:35:18.770 29857-30181/com.amplitude.tron.volksradio22 E/Adreno-GSL: <gsl_memory_alloc_pure:1971>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.
01-20 21:35:18.770 29857-30181/com.amplitude.tron.volksradio22 W/Adreno-GSL: <gsl_ldd_control:475>: ioctl fd 27 code 0x40080921 (IOCTL_KGSL_SHAREDMEM_FREE) failed: errno 22 Invalid argument
01-20 21:35:18.778 29857-30181/com.amplitude.tron.volksradio22 E/OpenGLRenderer: GL error:  Out of memory!
复制代码

有点蒙,就看出来了内存溢出。Google了一下,并没有什么有用信息。
着手分析(简单记录几个步骤,撞墙的步骤就不写了):

  1. 锁定范围
    由于是Flutter项目,所以怀疑是路由问题,写了一个跳转,不断点击,没有OOM
  2. 播放器问题,崩溃发生的页面是一个播放器页面。
    在原生页面中找了一个场景,不断跳转并回退,没有发生OOM。
  3. 此时已经有点接近崩溃,重新梳理问题。OOM,要么申请了大内存,要么就是泄漏了,看了一眼代码
@Override
protected void onDestroy() {
    super.onDestroy();
    //log  -->2
    if (videoView != null) {
        videoView.release();
        //log  -->1
    }
}
复制代码

明明有释放呀,释放的地方(1)加个log,居然没有打印,一度怀疑onDestroy没有执行,在加log(2),有打印。 4. 貌似找到了有问题的点,肯定是videoView为null,看了一下super。

@Override
protected void onDestroy() {
    if (mPresenter != null)
        mPresenter.detachView();
    super.onDestroy();
}

在看父类
@Override
protected void onDestroy() {
    super.onDestroy();
    mUnBinder.unbind();
}

看一下unbind(),注意是自动生成的实现类
@Override
@CallSuper
public void unbind() {
  LivePlayPreviewActivity target = this.target;
  if (target == null) throw new IllegalStateException("Bindings already cleared.");
  this.target = null;
  //就是这里
  target.videoView = null;
}

复制代码

在父类unbind的时候把view置空了,擦了一把汗,原来坑在这里
Butter Knife在解绑的时候会把view的引用置空,哎! 调整一下代码顺序

@Override
protected void onDestroy() {
    if (videoView != null) {
        videoView.release();
    }
    super.onDestroy();
}
复制代码

完美解决,提交!