panpf / sketch

Sketch is an image loading library designed for Compose Multiplatform and Android View. It is powerful and rich in functions. In addition to basic functions, it also supports GIF, SVG, video thumbnails, Exif Orientation, etc.
Apache License 2.0
2.01k stars 307 forks source link

当调用 setZoomEnabled 后存在内存泄漏问题 #141

Closed ParadiseHell closed 3 years ago

ParadiseHell commented 3 years ago

环境

必要知识点

Kotlin synthetic 在 Fragment 生命周期执行 onDestoryView 后会将 View 的引用置为 null, 之后再获取 View 则会抛异常。

场景复现

  1. SketchImageView 用于 Fragment 中,通过 Monkey 测试不停打开 Fragment、点击 SketchImageView、关闭 Fragment.
  2. SketchImageView 添加了一个 ClickListener, 回调被执行后会通过 Kotlin synthetic 获取 View 处理一些业务逻辑。
  3. Monkey 测试出 10+ 的崩溃。

崩溃原因

FunctionCallbackView 的 clickListenerProxy 虽然弱引用了 SketchImageView, 但是在调用 setZoomEnabled 后会创建 ImageZoomFunction, ImageZoomFunction 接着创建 ImageZoomer, 但是 ImageZoomer 是强引用 SketchImageView 的,这就导致 FunctionCallbackView 的所有 Listener 的弱引用全部失效。

具体到我们的代码中就是会导致设置 OnClickListener 后,因为 Fragment 已经销毁,通过 Kotlin synthetic 获取 View 直接崩溃。

其他

我只是定位到问题,没有仔细看代码,所以可能提 PR 就可能是小修小补,无法根治问题,还希望之后版本修复一下这个问题。

panpf commented 3 years ago

收到你的反馈,你要解决的是崩溃还是泄露?

首先应该不存在泄露问题,因为 ImageZommer 是随着 SketchImageView 生命周期走 的,SketchImageView销毁了,ImageZommer也会跟着销毁,所以即使强引用也没事

其次在 OnClick 执行的时候如果 Fragment 已经销毁了,那么你这时候 get view 就应该返回 null,这个逻辑没有毛病。你加个过滤或者在 setOnClick 之前 get view,然后 onclick 执行的时候就直接用

ParadiseHell commented 3 years ago

解决泄漏问题。 我这边的场景表明 Fragment 已经销毁了,但是 SketchImageView 还没有被销毁,并出触发了 onClick 事件,所以认为是泄漏导致的问题。

我确实因为没有看过项目源码,所以可能理解上有些问题,我这边已经在 onClick 回调判断了是否为 null, 暂时解决这个问题。

或者说 Android 本身就存在这种问题,页面已经销毁了,但是页面的 View 的点击事件在某些场景依然有可能被触发的可能性,不知道这块你是否有了解,如果有还望科普下。

panpf commented 3 years ago

View 泄露只是引用泄露, 只会导致内存无法释放,并不会导致触发 onClick。 只有接收到触摸事件才会触发 onClick,如果你没有任何点击 view 的操作而触发了 onClick,那么就要顺着这条线索找 bug。

ParadiseHell commented 3 years ago

好的,谢谢🙏

panpf commented 9 months ago

单独的 zoomimage ( https://github.com/panpf/zoomimage )库来了,支持 compose 和 view,两个版本逻辑和体验完全一致

新的 zoomimage 库在 sketch-zoom 的基础上完全重构,用户体验全面提升,除修复了一些 bug 之外还新支持了子采样碎片的动画和清晰度渐变以及支持 glide、picasso、coil、等图片加载器

目前已经到了公开测试的 beta 阶段,欢迎到 release 页面下载 APK 体验效果

sketch-zoom 模块以后将不再提供更新