使用应用程序上下文滑动图像加载
Glide image loading with application context
我在我的 android 应用程序中使用 glide 进行图像加载,以避免任何崩溃,我正在使用应用程序上下文加载图像。这对应用程序和内存的性能有何影响?
What will be effect of this on performance of application and memory?
Glide 提供这么多 .with()
方法是有原因的:它遵循生命周期。
想象一个动态添加到 Activity 的 Fragment
。在其 onCreateView
方法中,它开始 Glide 加载 3MB 图像。现在,如果用户按下后退按钮并且 Fragment 被删除或整个 activity 关闭怎么办?
- 如果你使用
with(getActivity().getApplicationContext())
什么都不会发生,所有 3MB 的数据都被下载然后解码,缓存,甚至可能设置到 ImageView,然后被垃圾收集,因为对它的唯一引用来自滑翔内部。
- 如果你使用
with((Fragment)this)
Glide 订阅了 Fragment 的生命周期事件,一旦 Fragment 停止,任何未完成的请求都应该暂停;当销毁时,所有未决请求将被清除。这意味着图像下载将中途停止,并且该死片段将不再使用资源。
- 如果你使用
with(getActivity())
Glide 订阅了 Activity 的生命周期事件并且发生了与上面相同的事情,但只有当 Activity 被停止或销毁时才会发生。
所以最好的做法是使用尽可能接近的 context/fragment 来避免未使用的请求完成! (还有一种手动停止加载的方法: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 请求与所有者的生命周期同步的通用解决方案。可以从任何地方调用:Activity、片段、RV 适配器、自定义视图等
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 生命周期库中。它提供了 Activity 或片段视图的生命周期 (viewLifecycleOwner
) 这个特定的 ImageView 附加到。您将需要从视图中传递应用程序上下文,以确保 Glide 库不会调用回调本身。
我在我的 android 应用程序中使用 glide 进行图像加载,以避免任何崩溃,我正在使用应用程序上下文加载图像。这对应用程序和内存的性能有何影响?
What will be effect of this on performance of application and memory?
Glide 提供这么多 .with()
方法是有原因的:它遵循生命周期。
想象一个动态添加到 Activity 的 Fragment
。在其 onCreateView
方法中,它开始 Glide 加载 3MB 图像。现在,如果用户按下后退按钮并且 Fragment 被删除或整个 activity 关闭怎么办?
- 如果你使用
with(getActivity().getApplicationContext())
什么都不会发生,所有 3MB 的数据都被下载然后解码,缓存,甚至可能设置到 ImageView,然后被垃圾收集,因为对它的唯一引用来自滑翔内部。 - 如果你使用
with((Fragment)this)
Glide 订阅了 Fragment 的生命周期事件,一旦 Fragment 停止,任何未完成的请求都应该暂停;当销毁时,所有未决请求将被清除。这意味着图像下载将中途停止,并且该死片段将不再使用资源。 - 如果你使用
with(getActivity())
Glide 订阅了 Activity 的生命周期事件并且发生了与上面相同的事情,但只有当 Activity 被停止或销毁时才会发生。
所以最好的做法是使用尽可能接近的 context/fragment 来避免未使用的请求完成! (还有一种手动停止加载的方法: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 请求与所有者的生命周期同步的通用解决方案。可以从任何地方调用:Activity、片段、RV 适配器、自定义视图等
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 生命周期库中。它提供了 Activity 或片段视图的生命周期 (viewLifecycleOwner
) 这个特定的 ImageView 附加到。您将需要从视图中传递应用程序上下文,以确保 Glide 库不会调用回调本身。