Видалити зображення з кешу в бібліотеці Glide


75

Я використовую Glide в одному зі своїх проектів, щоб показати зображення з файлу.

Нижче мій код, як я показую зображення:

Glide.with(DemoActivity.this)
     .load(Uri.parse("file://" + imagePath))
     .into(mImage);

Зображення в цьому місці ( imagePath) постійно змінюється. За замовчуванням Glide кешує зображення, яке воно відображає в ImageView. Через це Glide показував перше зображення з кешу для нових зображень у цьому місці.

Якщо я поміняю зображення за місцем розташування imagePathна якесь інше зображення з такою ж назвою, тоді Glide показує перше зображення замість нового.

Два запити:

  1. Чи можна завжди зображення з файлу, а не кеш? Таким чином проблема буде вирішена.

  2. Чи можна очистити зображення з кешу перед тим, як отримувати нещодавно замінене зображення? Це також вирішить проблему.

Відповіді:


148

Ось як я вирішив цю проблему.

Спосіб 1: Коли URL-адреса змінюється при зміні зображення

Glide.with(DemoActivity.this)
    .load(Uri.parse("file://" + imagePath))
    .diskCacheStrategy(DiskCacheStrategy.NONE)
    .skipMemoryCache(true)
    .into(mImage);

diskCacheStrategy () можна використовувати для обробки кешу диска, і ви можете пропустити кеш пам'яті за допомогою методу skipMemoryCache ().

Спосіб 2: Однак, коли URL-адреса не змінюється, зображення змінюється

Якщо ваша URL-адреса залишається незмінною, вам потрібно використовувати Signature для кешу зображень.

Glide.with(yourFragment)
     .load(yourFileDataModel)
     .signature(new StringSignature(yourVersionMetadata))
     .into(yourImageView);

Підпис Glide () пропонує можливість змішувати додаткові дані з ключем кешу.

  • Ви можете використовувати, MediaStoreSignatureякщо ви отримуєте вміст із медіамагазину. MediaStoreSignatureдозволяє змішувати час, змінений дату, тип mime та орієнтацію елемента сховища медіа в ключ кешу. Ці три атрибути надійно фіксують редагування та оновлення, дозволяючи кешувати медіа-сховища великих пальців.
  • Ви також можете StringSignatureдля вмісту, збереженого як Файли, змішати час зміни дати файлу.

Це працює для мене. Переконайтеся, що ви насправді змінюєте зображення.
Хуан Хосе Мелеро Гомес

15
Зверніть увагу, що з Glide v4 StringSignatureзамінено на ObjectKey, див. Ghide v4 Кешування
Кучеряве

У цьому методі, якщо ми маємо однакову URL-адресу з іншою версією, чи завантажується вона відносну версію, коли ми передаємо версію?
Ішан Фернандо

3
Ви не вирішили проблему 2 "Чи можна очистити зображення з кешу перед тим, як отримувати нещодавно замінене зображення? Це також вирішить проблему."
Нік

1
хоча це працює, завантажувати зображення щоразу цим методом болісно повільно
The Fluffy T Rex

55

Як пояснено в розділі Кешування та інвалідація кешу wiki Glide:

Оскільки імена файлів - це хешовані ключі, немає хорошого способу просто видалити всі кешовані файли на диску, які відповідають певній URL-адресі чи шляху до файлу. Проблема була б простішою, якби вам було дозволено завантажувати або кешувати оригінальне зображення, але оскільки Glide також кешує мініатюри та забезпечує різні трансформації, кожна з яких призведе до створення нового файлу в кеші, відстеження та видалення кожної кешованої версії зображення важко.

На практиці найкращий спосіб анулювати кеш-файл - це змінити> ідентифікатор при зміні вмісту (url, uri, шлях до файлу тощо).

Оскільки ви не можете змінити шлях до файлу, Glide пропонує API підпису (), що дозволяє встановити деякі додаткові дані, що підлягають змішуванню, до ключів пам’яті та кеш-пам’яті диска, що дає змогу абоненту більше контролювати, коли кешовані дані недійсні.

Якщо ви хочете перезавантажувати кожен раз, коли зображення з диска, ви можете змінити свій код так:

Glide.with(DemoActivity.this)
     .load(Uri.parse("file://" + imagePath))
     .signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
     .into(mImage);

Це ідеально підходить для моїх потреб. У мене є версія для моїх даних, тому просто додавання .signature(new StringSignature(Integer.toString(data.getVersion())))змушує оновлювати зображення, коли версія змінюється.
Krøllebølle

@Mattia Maestrini Дякую, ваше рішення оновило одне зображення в кеш до System.currentTimeMillis()?
DolDurma

1
Тож я здогадуюсь, що це не забруднить каталог кеш-пам’яті, оскільки мається на увазі, що URL-адреса є постійною, правда? Це означає, що він перезапише попередні записи кешу?
TheRealChx101

для використання .signature(ObjectKey(System.currentTimeMillis())))
Котліна

35

Є два способи обробити кеш-пам’ять Glide ,

Перший шлях: - Додайте нижче з реалізацією ковзання

.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)

Другий спосіб:

Якщо ви зможете визначити зміни зображення, введіть нове ім'я файлу нижче,

.signature(new StringSignature(String.valueOf(fileName)))

або ви хочете кожен раз завантажувати останні зображення, використовуйте нижче

.signature(new StringSignature(String.valueOf(System.currentTimeMillis())))

Сподіваюся, це допомагає.


32

Це видалить кеш-пам’ять, яка зберігається Glide, і це слід зробити у фоновому режимі, інакше викине виняток

new Thread(new Runnable() {
          @Override
          public void run() {
             Glide.get(MainActivity.this).clearDiskCache();
          }
     }).start();

1
тоді як система вирішить зупинити запущений потік відразу після видалення кешу?
Яш Агравал

1
@YashAgrawal: Це буде вирішувати внутрішня структура. Тож не потрібно про це турбуватися
Ананд Савяні

23

Були проблеми з Glide 4.2.0, StringSignatureне було вирішено.

Схоже, StringSignatureвін уже недоступний, і вам доведеться використовувати його ObjectKey.

Тож код виглядає так

Glide.with(imageView).
load(pathToImage).
apply(new RequestOptions().signature(new ObjectKey("signature string"))).
into(imageView);

16

Якщо ви зберігаєте зображення в тій самій відомій назві файлу, що і конвенція, і хочете зробити недійсним кеш Glide лише тоді, коли файл змінився, використання позначки часу модифікації файлу може добре працювати.

Я використовував таку конвенцію для зображень аватарів, які завантажував до Fileоб’єктів за межами Glide, а потім використовував Glide просто для того, щоб ефективно змінити розмір і зробити їх круглими тощо.

Тож я в підсумку використав StringSignatureстратегію із значенням позначки часу lastChanged часу як підпис. Ось як виглядає вільний код для цього:

Glide.with(this)
        .load(avatarFile)
        .diskCacheStrategy(DiskCacheStrategy.RESULT)
        .signature(new StringSignature(String.valueOf(avatarFile.lastModified())))
        .into(ivProfile);
}

де avatarFileмій java.io.Fileоб'єкт, звичайно.


14

У мене були проблеми з встановленням підпису за допомогою Glide версії 4. * з Kotlin. Через деякий час я закінчив із цим:

fun ImageView.loadUrl(url: String) {
    var requestOptions = RequestOptions()
    requestOptions.signature(ObjectKey(System.currentTimeMillis()))
    Glide.with(this).load(url).apply(requestOptions).into(this)
}

Це функція розширення для ImageView, і вона використовується таким чином:

 imageView.loadUrl(url)

Сподіваюся, це комусь допоможе


1
саме те, що мені потрібно.
Антон Дерев’янко

12

Для бібліотеки Glide 4.3. + Вам потрібно щось подібне,

Glide.with(context)
    .load(image_path)
    .apply(new RequestOptions()
                        .diskCacheStrategy(DiskCacheStrategy.NONE)
                        .skipMemoryCache(true))
    .into(imge_view);

12

В останніх версіях ми повинні використовувати RequestOptions

RequestOptions Надає незалежні від типу опції для налаштування навантажень за допомогою Glide в останніх версіях Glide.

Створіть об’єкт RequestOptions і використовуйте його, коли ми завантажуємо зображення.

 RequestOptions requestOptions = new RequestOptions()
                        .diskCacheStrategy(DiskCacheStrategy.NONE) // because file name is always same
                        .skipMemoryCache(true);

 Glide.with(this)
           .load(photoUrl)
           .apply(requestOptions)
           .into(profile_image);

6

підпис GlideApp

    GlideApp.with(imageView)
            .load(url)
            .signature(new ObjectKey(System.currentTimeMillis()))
            .placeholder(R.drawable.sky)
            .error(R.drawable.sky)
            .into(imageView);

4

Це спрацювало для мене

  //use  diskCacheStrategy(DiskCacheStrategy.NONE) after skipMemoryCache(true) 
         Glide.with(this)
            .load(image)
            .skipMemoryCache(true) 
            .diskCacheStrategy(DiskCacheStrategy.NONE)
            .into(imageview);

4

І нарешті, реалізація Kotlin (для фрагментів):

Glide.with(activity)
            .load(url)
            .apply(RequestOptions()
                    .diskCacheStrategy(DiskCacheStrategy.NONE)
                    .skipMemoryCache(true))
            .into(myImageView)

4

Я працював над цим цілими днями, і всі вищезазначені рішення просто повільні, як лінивець.

Я знаю, що ви, мабуть, читали це раніше і ігнорували, тому що думали, що, можливо, знадобиться багато роботи, щоб змінити ваш код. Але якщо серйозно, то воно того варте. Продуктивність, наскільки я можу зрозуміти, перевершує всі інші представлені методи, це рекомендоване рішення Glide, І вам не потрібно пропускати кеш чи створювати підписи, щоб він також зберігав ваш код чистішим.

ВІД ковзання:

На практиці найкращий спосіб анулювати кеш-файл - це змінити свій ідентифікатор при зміні вмісту (url, uri, шлях до файлу тощо), коли це можливо. - https://bumptech.github.io/glide/doc/caching.html

РІШЕННЯ: Змініть назву зображення, коли користувач завантажує нове зображення. Отримайте ім’я файлу та скористайтеся цим, наприклад. Як тільки URL-адреса зображення зміниться, Glide зрозуміє, що ви змінили зображення, і відповідно оновить кеш. Це, безумовно, дало мені найкращі результати.

ПРИ ВИКОРИСТАННІ:

.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)

Він ніколи не кешує зображення, і це дійсно змушує зображення завантажуватися повільно. Можна подумати, що підписи є кращими для виконання, але мені вони здалися такими ж повільними.


1

Щоб скористатися кешем, що надається Glide, і гарантувати, що кожен раз відображається правильне зображення, ви можете використовувати API signature () .

Все, що вам потрібно зробити, це встановити як підпис інформацію, яка стосується файлу зображення. Коли ви замінюєте цей файл, інформація також змінюється, і Glide знає, що він повинен перезавантажити його, ігноруючи кеш.

Дійсною інформацією може бути дайджест (наприклад, SHA-1), розрахований на вміст файлу.

Glide.with(context)
   .load(inputFile)
   .signature(new StringSignature(sha1(inputFile)))
   .into(targetImageView);

Тут я знайшов наступну реалізацію функції sha1 ():

public static String sha1(final File file) throws NoSuchAlgorithmException, IOException {
   final MessageDigest messageDigest = MessageDigest.getInstance("SHA1");

   try (InputStream is = new BufferedInputStream(new FileInputStream(file)) {
     final byte[] buffer = new byte[1024];
     for (int read = 0; (read = is.read(buffer)) != -1;) {
       messageDigest.update(buffer, 0, read);
     }
   }

   // Convert the byte to hex format
   try (Formatter formatter = new Formatter()) {
     for (final byte b : messageDigest.digest()) {
       formatter.format("%02x", b);
     }
     return formatter.toString();
   }
}

здається, працює разом із використанням підпису, дискового кешу та skipmemory.
Panache

1

Цей працював у мене!

Glide.with(DemoActivity.this)
    .load(Uri.parse("file://" + imagePath))
    .diskCacheStrategy(DiskCacheStrategy.NONE)
    .skipMemoryCache(true)
    .into(mImage);

1

Я використовував Glide для завантаження a File, і ось що я в кінцевому підсумку зробив, щоб переконатися, що кеш диска Glide був недійсним щоразу, коли мій файл змінювався (хоча він мав однаковий шлях):

Glide.with(context)
    .load(bitmapFile)
    .signature(new ObjectKey(bitmapFile.lastModified()))
    .into(imageView);


0

1) Спочатку очистіть кеш диска .

private class ClearGlideCacheAsyncTask extends AsyncTask<Void, Void, Boolean>{

        private boolean result;

        @Override
        protected Boolean doInBackground(Void... params) {
            try {
                Glide.get(getContext()).clearDiskCache();
                result = true;
            }
            catch (Exception e){
            }
            return result;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            if(result)
                Toast.makeText(getActivity(), "cache deleted", Toast.LENGTH_SHORT).show();
        }
    }

Ви можете зателефонувати зі свого інтерфейсу за допомогою new ClearGlideCacheAsyncTask ().execute();

2) Очистити кеш пам'яті

// This method must be called on the main thread.
Glide.get(context).clearMemory();

Джерело: https://bumptech.github.io/glide/doc/caching.html

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.