Загрузка скользящего изображения в контексте приложения

Я использую 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 не вызывают сами обратные вызовы.

Другие вопросы по тегам