Неверный кеш в Пикассо

Я загружаю изображение с диска с помощью Picasso, например, Picasso.with(ctx).load(new File("/path/to/image")).into(imageView), но всякий раз, когда я сохраняю новое изображение в этом файле и обновляю ImageViewУ Пикассо все еще есть кэшированное растровое изображение.

Можно ли сделать недействительным кеш в Пикассо?

14 ответов

Решение

В последних версиях Picasso появился новый метод для аннулирования без каких-либо обходных путей, поэтому я думаю, что пользовательский класс PicassoTools, упомянутый ранее, теперь в этом случае устарел

Picasso.with(getActivity()).invalidate(file);

На самом деле, основываясь на вашем собственном ответе, есть более простой способ сделать это без разветвления библиотеки. Добавьте этот класс в пакет com.squareup.picasso.

package com.squareup.picasso;

public class PicassoTools {

    public static void clearCache (Picasso p) {
        p.cache.clear();
    }
}

Поскольку кеш имеет видимость пакета, этот класс утилит может очистить кеш для вас. Вы просто должны это назвать:

PicassoTools.clearCache(Picasso.with(context));

Прервать кэш-память и проверку дискового кэша, указав политику памяти с помощью флага: emoryPolicy.NO_CACHE и NetworkPolicy.NO_CACHE, как показано ниже:

   mPicasso.with(mContext)
            .load(url)
            .memoryPolicy(MemoryPolicy.NO_CACHE )
            .networkPolicy(NetworkPolicy.NO_CACHE)
            .resize(512, 512)
            .error(R.drawable.login)
            .noFade()
            .into(imageView);

Попробуй использовать:

Picasso.with(ctx).load(new File("/path/to/image")).skipMemoryCache().into(imageView)

Порядок поиска изображений в Picasso: Кэш памяти -> Кэш диска -> Сеть

Таким образом, есть несколько сценариев, которые нам нужны для аннулирования кэша в Picasso:

1. Неправильный кэш памяти:

  • Usercase: когда изображение уже обновлено в кеше диска или на удаленном хосте
  • Решение: очистить кэш Url, File, Uri, если он существует

    mPicasso.with(appContext).invalidate(File);
    mPicasso.with(appContext).invalidate(Url);
    mPicasso.with(appContext).invalidate(Uri);
    

,

2. Недействительный кеш памяти и дисковый кеш онлайн

※ примечание: онлайн означает обновление непосредственно в ImageView

  • Случай пользователя: изображение обновлено на удаленном хосте

  • Решение: прервать образ в кеше памяти и на диске, а затем запросить образ на удаленном хосте.

    mPicasso.with(appContext)
        .load(url)
        .memoryPolicy(MemoryPolicy.NO_CACHE )
        .networkPolicy(NetworkPolicy.NO_CACHE)
        .into(imageView);
    

    -> Прервать кеш памяти и дисковый кеш

,

3. Недействительный кэш-память и дисковый кэш автономно

※ примечание: автономное обновление означает, что обновление не обновляется до ImageView, просто фоновая загрузка для использования позже

  • Случай пользователя: вы знаете, что изображение на удаленном хосте обновлено, но хотите обновлять кеш только для последующего использования (не для обновления в виде изображения)
  • Решение: получить только

     mPicasso.with(appContext)
        .load(url)
        .memoryPolicy(MemoryPolicy.NO_CACHE)
        .networkPolicy(NetworkPolicy.NO_CACHE)
        .fetch();
    

※ Примечание: использование fetch() хорошо, но оно также потребляет сетевой ресурс, поэтому, пожалуйста, внимательно рассмотрите сценарий 4 ниже для лучшего решения.

4. Неправильный кэш памяти и дисковый кеш в автономном режиме, если дисковый кеш существует

  • Случай пользователя: аннулировать кеш, только если он уже существует в кеше диска
  • Решение: перед загрузкой следует проверить диск с помощью параметра: кэш NetworkPolicy.OFFLINE.

     mPicasso.with(appContext)
        .load(url)
        .memoryPolicy(MemoryPolicy.NO_CACHE)
        .networkPolicy(NetworkPolicy.OFFLINE)
        .fetch(new Callback() {
            @Override
            public void onSuccess() {
                //Success: mean disk cache exist -> should do actual fetch
                picasso.load(url).fetch();
            }
    
            @Override
            public void onError() {
            //Failed: mean disk cache not exist
        }
    });
    

Picasso - замечательная библиотека, я надеюсь, что Squareup добавит больше удобных API для управления кешем в будущем.

Что вы можете сделать, если вы хотите удалить весь кэш сразу, это создать кастом Picasso.LruCache, а затем используйте clear метод на это.

Вот образец:

Picasso.Builder builder = new Picasso.Builder(this);
LruCache picassoCache = new LruCache(this);
builder.memoryCache(picassoCache);
Picasso.setSingletonInstance(builder.build());

Чтобы очистить кеш:

picassoCache.clear();

Другой вариант - удалить сам каталог кеша, например, при запуске приложения:

deleteDirectoryTree(context.getCacheDir());

где:

/**
 * Deletes a directory tree recursively.
 */
public static void deleteDirectoryTree(File fileOrDirectory) {
    if (fileOrDirectory.isDirectory()) {
        for (File child : fileOrDirectory.listFiles()) {
            deleteDirectoryTree(child);
        }
    }

    fileOrDirectory.delete();
}

Это удаляет весь каталог кэша, что хорошо, если вы хотите имитировать первое использование вашего приложения. Если вы хотите удалить только кеш Пикассо, добавьте к пути "кеш Пикассо".

Вы можете очистить кеш изображений Пикассо, установив собственный кеш и очистив его. Этот код был протестирован на Picasso 2.5.0

private Picasso picasso;
private LruCache picassoLruCache;

picassoLruCache = new LruCache(context);

// Set cache
picasso = new Picasso.Builder(context) //
        .memoryCache(picassoLruCache) //
        .build();

// Clear cache
picassoLruCache.clear();

Не зацикливается, но этот подход решил мою проблему с кешем и Пикассо. Используйте это только тогда, когда вы хотите аннулировать кеш для определенного URL, этот подход медленный и, вероятно, не правильный способ, но работает для меня.

    String url = "http://www.blablabla.com/Raiders.jpg";
    Picasso.with(this).invalidate(url);
    Picasso.with(this)
            .load(url)
            .networkPolicy(
                    NetworkUtils.isConnected(this) ?
                            NetworkPolicy.NO_CACHE : NetworkPolicy.OFFLINE)
            .resize(200, 200)
            .centerCrop()
            .placeholder(R.mipmap.ic_avatar)
            .error(R.mipmap.ic_avatar)
            .into(imageView);

Очень важная часть отсутствует в принятом ответе здесь. Я нашел хитрость здесь: http://blogs.candoerz.com/question/124660/android-image-cache-is-not-clearing-in-picasso.aspx

Просто вызов следующей строки не очистит кэш фотографии при использовании пользовательских параметров, таких как изменение размера, обрезка по центру и т. Д. При отображении исходного изображения.

Picasso.with(getContext()).invalidate(file);

Решение:

При отображении изображения используйте stableKey() метод.

Picasso.with(getContext()).load(new File(fileUri))
                         .skipMemoryCache()
                         .placeholder(R.drawable.placeholder)
                         .stableKey(fileUri)
                         .into(imageview);

Затем вы можете очистить кэш этого файла позже, вызвав это:

Picasso.with(getContext()).invalidate(fileUri);

Надеюсь, это поможет.

Вы можете пропустить кеш памяти skipMemoryCache()

см. следующее

        Picasso.with(this)
            .load(IMAGE_URL)
            .skipMemoryCache()
            .placeholder(R.drawable.placeholder)
            .error(R.drawable.no_image)
            .into(mImageViewPicasso);

Gradle compile "com.squareup.picasso:picasso:2.4.0"

Другой вариант - сохранить новое изображение в файл, отличный от исходного. Поскольку кэш растрового изображения Picasso отключен от пути к файлу, загрузка нового изображения из другого файла приведет к отсутствию кэша. Это также имеет побочное преимущество - нет необходимости очищать весь кеш.

Использование shutdown() вместо этого согласно исходному коду; Завершение работы прекратит прием дальнейшего запроса, а также очистит весь кеш

 /** Stops this instance from accepting further requests. */
  public void shutdown() {
    if (this == singleton) {
      throw new UnsupportedOperationException("Default singleton instance cannot be shutdown.");
    }
    if (shutdown) {
      return;
    }
    cache.clear();
    cleanupThread.shutdown();
    stats.shutdown();
    dispatcher.shutdown();
    for (DeferredRequestCreator deferredRequestCreator : targetToDeferredRequestCreator.values()) {
      deferredRequestCreator.cancel();
    }
    targetToDeferredRequestCreator.clear();
    shutdown = true;
  }

Также вы не можете отключить экземпляр Singleton. Таким образом, вы должны иметь переменную экземпляра для Picasso, Не забывайте переинициализировать экземпляр Picasso каждый раз, когда вы shutdown() это для того, чтобы использовать его

File f = new File(path, name);
Picasso.with(this).invalidate(Uri.fromFile(f));
Другие вопросы по тегам