【发布时间】:2022-03-22 21:14:06
【问题描述】:
我在我的 android 应用程序中使用 glide 进行图像加载,以避免任何崩溃,我正在使用应用程序上下文加载图像。这会对应用程序和内存的性能产生什么影响?
【问题讨论】:
标签: android performance android-glide
我在我的 android 应用程序中使用 glide 进行图像加载,以避免任何崩溃,我正在使用应用程序上下文加载图像。这会对应用程序和内存的性能产生什么影响?
【问题讨论】:
标签: android performance android-glide
这会对应用程序和内存的性能产生什么影响?
Glide 提供这么多.with() 方法是有原因的:它遵循生命周期。
想象一个动态添加到活动中的Fragment。在其onCreateView 方法中,它启动了一个 3MB 图像的 Glide 加载。现在,如果用户按下后退按钮并且 Fragment 被移除或整个 Activity 被关闭怎么办?
with(getActivity().getApplicationContext()),什么都不会发生,所有 3MB 的数据都会被下载,然后解码,缓存,甚至可能设置到 ImageView,然后被垃圾收集,因为唯一的引用来自 Glide 内部。
with((Fragment)this)Glide 订阅Fragment 的生命周期事件,并且一旦Fragment 停止,任何未完成的请求都应该暂停;当被销毁时,所有待处理的请求都会被清除。这意味着图像下载将中途停止,该死片段将不再使用任何资源。with(getActivity()) Glide 订阅 Activity 的生命周期事件,并且发生与上述相同的事情,但仅在 Activity 停止或销毁时发生。因此,最佳做法是使用最接近的上下文/片段来避免未使用的请求完成! (还有一种手动停止加载的方法:Glide.clear(ImageView|Target)。)
要在实践中应用这一点,请尽可能使用with(this),但如果不是,例如在适配器或集中式图像加载方法中,请传入RequestManager glide作为参数并使用glide.load(...,用于示例:
static loadImage(RequestManager glide, String url, ImageView view) {
glide.load(url).into(view);
}
或在适配器中:
class MyAdapter extends WhichEveryOneYouUse {
private final RequestManager glide;
MyAdapter(RequestManager glide, ...) {
this.glide = glide;
...
}
void getView/onBindViewHolder(... int position) {
// ... holder magic, and get current item for position
glide.load... or even loadImage(glide, item.url, holder.image);
}
}
并从 Activity/Fragment 中使用这些:
loadImage(Glide.with(this), url, findViewById(R.id.image));
// or
list.setAdapter(new MyAdapter(Glide.with(this), data));
【讨论】:
Glide.with(view.getContext()) 实际上等效于Glide.with(this),因为RequestManagerRetriever.get(Context context) 检查上下文是否是Activity 的实例并适当地转换它,例如get((Activity)context)。因此,无论哪种方式,它最终都会使用相同的 get(Activity) 方法。
Glide.with(this).onDestroy()?假设我们在Glide.with().. 调用中使用正确的Context,因为Glide 将挂钩到Activity/Fragments 生命周期?
load,Coil 将使用 Activity 的生命周期。但是,Coil 和 Glide 都会响应 View.onDetach 事件,这些事件在 Fragment 被移到 backstack 时触发。此外,由于 Coil 使用 AndroidX 生命周期组件,因此在已销毁的 Activity 内部发出的任何请求都将立即取消。
private fun RequestManager.syncWithLifecycleOwner(view: View): RequestManager {
val syncRequest = object : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) = onStart()
override fun onStop(owner: LifecycleOwner) = onStop()
override fun onDestroy(owner: LifecycleOwner) {
onDestroy()
owner.lifecycle.removeObserver(this)
}
}
view.findViewTreeLifecycleOwner()?.lifecycle?.addObserver(syncRequest)
return this
}
然后你可以像这样制作一个简单的扩展函数:
fun ImageView.loadUrl(url: String) {
Glide
.with(context.applicationContext)
.syncWithLifecycleOwner(this)
.load(url)
.into(this)
}
findViewTreeLifecycleOwner() 存在于 AndroidX 生命周期库中。它提供了这个特定 ImageView 附加到的 Activity 或 Fragment View 的生命周期 (viewLifecycleOwner)。您需要从视图中传递应用程序上下文,以确保 Glide 库本身不会调用回调。
【讨论】: