Задержка с простым переходом к общему элементу с использованием Glide

У меня очень простой переход между двумя действиями, и иногда изображение останавливается посередине, отстает, мигает черным цветом.

Я много раз использовал общие элементы-переходы с Glide, но на этот раз я не могу сделать так, чтобы он не отставал.

это первое действие:

val intent = Intent(this, MediaZoomImageActivity::class.java)
intent.putExtra(MediaZoomActivity.ZOOM_MEDIA_URL, submission.imageUrl)

val bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(this,
            post_image_parallax, ViewCompat.getTransitionName(post_image_parallax)).toBundle()

startActivity(intent, bundle)

это второе действие:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_zoom_image)
    postponeEnterTransition()

    back.setOnClickListener { finish() }

    val url = intent.getStringExtra(ZOOM_MEDIA_URL)
    Glide.with(this)
            .load(url)
            .apply(RequestOptions().diskCacheStrategy(DiskCacheStrategy.RESOURCE))
            .into(media_zoom_image)

    media_zoom_image.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
        override fun onPreDraw(): Boolean {
            media_zoom_image.viewTreeObserver.removeOnPreDrawListener(this)
            startPostponedEnterTransition()

            return true
        }
    })

это макет для второго действия:

  1. ограничениеМакет
  2. -кнопка возврата (кнопка изображения)
  3. -изображение (ImageView)

это анимация:

<changeBounds
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="200" />

Это очень просто, но я не могу уложить это в голове. На втором изображении изначально был какой-то слушатель, использующий жесты, и я подумал, что причина в этом, но, комментируя все, все равно происходит это отставание. Изображение в первом действии является целью другого общего элемента-перехода с тем же именем перехода, может быть проблема в этом? Я делаю что-то неправильно? Это проблема с ConstraintLayout? Есть ли проблема с Glide?

Заранее спасибо за помощь.


person Luca Pellizzari    schedule 26.12.2017    source источник


Ответы (1)


Вместо использования PreDrawListener использование прослушивателя со скольжением исправит ситуацию. Похоже проблема с синхронизацией

 Glide
            .with(this)
            .asBitmap()
            .load(url)
            .apply(RequestOptions().diskCacheStrategy(DiskCacheStrategy.RESOURCE))
            .listener(new RequestListener<Bitmap>() {
                @Override
                public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
                    return false;
                }

                @Override
                public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
                    media_zoom_image.setImageBitmap(resource);
                    startPostponedEnterTransition();
                    return true;
                }
            })
            .into(media_zoom_image);

Убедитесь, что вы удалили

 media_zoom_image.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
    override fun onPreDraw(): Boolean {
        media_zoom_image.viewTreeObserver.removeOnPreDrawListener(this)
        startPostponedEnterTransition()

        return true
    }
})

ОБНОВЛЕНИЕ

Я обновил блок onResourceReady. Попробуйте, пожалуйста.

Glide
        .with(this)
        .asBitmap()
        .load(url)
        .apply(RequestOptions().diskCacheStrategy(DiskCacheStrategy.RESOURCE))
        .listener(new RequestListener<Bitmap>() {
            @Override
            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
                return false;
            }

            @Override
            public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
                startPostponedEnterTransition();
                return false;
            }
        })
        .into(media_zoom_image);

ОБНОВЛЕНИЕ 2

Вызовите postponeEnterTransition как можно раньше.

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);

postponeEnterTransition(); // Called it before set content. Try to call it before super.onCreate to see if it also works?

setContentView(R.layout.activity_zoom_image);
...
})

ОБНОВЛЕНИЕ 3

Оптимизируйте свои изображения. Для этого есть несколько онлайн-сайтов или инструментов, или вы можете обратиться к своему графическому дизайнеру.

Также вы можете увеличить продолжительность анимации, чтобы дать время для плавной загрузки.

<changeBounds
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300" />

Обратите внимание, что прослушиватель в glide запускается перед установкой растрового изображения для просмотра. Разница между Picasso и Glide: Picasso имеет параметр обратного вызова в методе into() как необязательный, который запускается onSuccess() после установки растрового изображения для просмотра. Таким образом, выполнение, которое делает наш общий переход прерывистым (ImageView#setBitmapImage), уже выполнялось, будучи отложенным. В этой ситуации Пикассо блистал немного больше.

person Emre Aktürk    schedule 26.12.2017
comment
С этим решением вроде реже или реже, но все равно есть. - person Luca Pellizzari; 28.12.2017
comment
Я не знаю, является ли это проблемой синхронизации, потому что кажется, что у него есть проблемы с некоторыми изображениями, а с некоторыми нет. Кроме того, это происходит только в первый раз, потому что, если я вернусь и сделаю это во второй раз, все будет гладко, может ли это быть проблемой кэширования? - person Luca Pellizzari; 28.12.2017
comment
Это время, проходящее для загрузки изображения в первый раз. Это должно работать, я думаю, проблема в том, что мы пытаемся перерисовать изображение во время анимации. Я собираюсь обновить ответ. Можешь попробовать? - person Emre Aktürk; 28.12.2017
comment
Некоторые изображения имеют меньший размер файла или разрешение. Это заставляет их загружаться и рисовать быстрее. Вот почему вы не всегда можете воспроизвести его. - person Emre Aktürk; 28.12.2017
comment
Стало лучше, один раз видел, и думаю это мой телефон (тестирую и на эмуляторе и на своем Nexus 6p). В начале он отстает, как будто изображение нужно перерисовывать, и это занимает немного времени. - person Luca Pellizzari; 28.12.2017
comment
Теперь есть другая проблема: если я удалю кеш и скачаю изображение, убедившись, что оно не запомнено, оно зависает на 1 или 2 секунды в ожидании startPostponedEnterTransition. Я перехожу от миниатюры к более крупному изображению, где пользователь может использовать жесты для увеличения во втором действии. К сожалению, я не могу оптимизировать изображения, так как загружаю их из Интернета, один пример, который я тестирую, - 1080x800. Как вы думаете, я должен уменьшить их выборку, когда я иду? создать понижающую дискретизацию ImageView? Я не знаю, как его сбалансировать, чтобы пользователь не видел увеличение зернистости. - person Luca Pellizzari; 28.12.2017
comment
Мы замораживаем пользовательский интерфейс для перехода к общему элементу. Лучшее, что мы можем сделать, это уменьшить размеры файлов исходных изображений с помощью инструментов и создать наши миниатюры из оригинальных (полноразмерных), и лучший трюк будет заключаться в том, чтобы при создании миниатюр из исходных размеров мы кэшировали исходные изображения :) Когда пользователь хочет чтобы увидеть полное изображение, оно уже кэшировано! Гладкий, как это может быть - person Emre Aktürk; 29.12.2017
comment
Что, если я использую миниатюру с тем же изображением .with thumbnail(0.1f), будет ли это работать? Мне придется сменить слушателя и вернуться к preDrawListener, верно? - person Luca Pellizzari; 29.12.2017
comment
Да, это сработает. Также вам необходимо убедиться, что опция DiskCacheStrategy позволяет сохранить оригинальную, а не сгенерированную миниатюру. Тогда вы закончили с этим кодом: d - person Emre Aktürk; 29.12.2017