Загрузка скользящего изображения в контексте приложения
Я использую glide для загрузки изображений в моем приложении для Android, чтобы избежать сбоев. Я загружаю изображения в контексте приложения. Как это повлияет на производительность приложения и память?
2 ответа
Как это повлияет на производительность приложения и память?
Glide предоставляет так много .with()
методы по причине: это следует жизненному циклу.
Представь себе Fragment
это динамически добавляется в активность. В своем onCreateView
Метод запускает скольжение изображения размером 3 МБ. Теперь, что если пользователь нажмет кнопку "Назад" и фрагмент будет удален или все действие будет закрыто?
- Если вы используете
with(getActivity().getApplicationContext())
ничего не произойдет, все 3 МБ данных загружаются, а затем декодируются, кэшируются, возможно, даже устанавливаются в ImageView, который затем собирается в мусор, потому что единственная ссылка на него была из внутренних данных Glide. - Если вы используете
with((Fragment)this)
Glide подписывается на события жизненного цикла Фрагмента, и как только Фрагмент останавливается, любой ожидающий запрос должен быть приостановлен; и когда уничтожено, все ожидающие запросы будут очищены. Это означает, что загрузка изображения остановится на полпути, и этот мертвый фрагмент больше не будет использовать ресурсы. - Если вы используете
with(getActivity())
Glide подписывается на события жизненного цикла Действия, и происходит то же самое, что и выше, но только когда Деятельность остановлена или уничтожена.
Поэтому лучше всего использовать ближайший контекст / фрагмент, чтобы избежать неиспользуемых завершений запросов! (Существует также ручной способ остановить нагрузку: 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, Fragment, RV Adapter, Custom View и т. д.
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 или Fragment View (
viewLifecycleOwner
), к которому прикреплен этот конкретный ImageView. Вам нужно будет передать контекст приложения из представления, чтобы убедиться, что библиотеки Glide не вызывают сами обратные вызовы.