Неверный кеш в Пикассо
Я загружаю изображение с диска с помощью 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));