结论:
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了一下,并没有什么有用信息。
着手分析(简单记录几个步骤,撞墙的步骤就不写了):
- 锁定范围
由于是Flutter项目,所以怀疑是路由问题,写了一个跳转,不断点击,没有OOM - 播放器问题,崩溃发生的页面是一个播放器页面。
在原生页面中找了一个场景,不断跳转并回退,没有发生OOM。 - 此时已经有点接近崩溃,重新梳理问题。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();
}
完美解决,提交!