AsyncTaskLoader 中的 "leaking" 上下文有那么糟糕吗?

Is "leaking" context inside AsyncTaskLoader that bad?

我有一个执行某些后台任务的 AsyncTaskLoader。在执行此任务时,它需要访问一些视图。 (不,我不能只是事先获得视图的值 - 它们是自定义视图,附有一些神奇的东西 - 请接受它)

但是,这会导致上下文泄漏,因为 AsyncTaskLoader 持有对上下文对象的引用。

没那么糟糕,对吧?就像旧视图在几分之一秒后被垃圾收集一样。-这是唯一的副作用,对吗?

根据记录,我需要引用的视图是 https://github.com/ArthurHub/Android-Image-Cropper 中的 CropImageView,我需要从 Loader 内部调用的方法是 view.getCroppedImage(width, height, CropImageView.RequestSizeOptions.RESIZE_INSIDE);

(不,由于某些原因,我不能使用预打包的异步版本的 getCroppedImage)

是的上下文泄漏很糟糕,我们必须手动避免它。AsyncWork 持有对 Context 的引用,Context 在任务完成之前不能被 GC: Context 内存泄漏。有两种解决方案:

1.Use一个context就是长寿了,反正Applicationcontext.
2.Tie 异步任务的生命与其持有引用的 context 的生命相同:在 onPause().

中取消它

是的,即使是很小的泄漏也是危险的,因为您永远不知道它可能泄漏多少内存。在您的示例中,当任何后台任务持有对 context 的引用时,它将不允许对 context 进行垃圾回收,从而浪费内存。这对于小对象来说很好,但是像 context, Bitmaps 这样的大对象拥有大量内存而不让 GC 收集它。

假设,您从 Activity A

开始了 Loader
A -> x memory ( x ~ very large memory comparatively )

尽管如此,loader仍在进行中,但您更改了移动设备的方向,这会创建具有相同内存量 x 的 Activity A 的新实例。理想情况下,Activity A 的旧实例应该被垃圾回收,但 GC 无法回收旧实例内存,因为它被强烈引用到后台任务。

因此,您需要在执行后台任务时注意泄漏,这可以通过两种方式完成 -

在销毁 activity 实例时取消 loader(或)将 contextweak reference 传递给加载器。