studio squareup library for adding android image caching picasso

android - squareup - picasso kotlin



¿Cómo uso el almacenamiento en caché de disco en Picasso? (7)

Estoy usando Picasso para mostrar la imagen en mi aplicación de Android:

/** * load image.This is within a activity so this context is activity */ public void loadImage (){ Picasso picasso = Picasso.with(this); picasso.setDebugging(true); picasso.load(quiz.getImageUrl()).into(quizImage); }

He habilitado la depuración y siempre muestra rojo o verde. Pero nunca aparece amarillo

Ahora, si cargo la misma imagen la próxima vez y no hay conexión a Internet, la imagen no se carga.

Preguntas:

  1. ¿No tiene caché de disco local?
  2. ¿Cómo habilito el almacenamiento en caché de disco, ya que usaré la misma imagen varias veces?
  3. ¿Debo agregar algún permiso de disco al archivo de manifiesto de Android?

1) Picasso por defecto tiene caché (ver ahmed hamdy answer)

2) Si realmente debe tomar una imagen de la memoria caché del disco y luego de la red, le recomiendo que escriba su propio programa de descarga:

public class OkHttpDownloaderDiskCacheFirst extends OkHttpDownloader { public OkHttpDownloaderDiskCacheFirst(OkHttpClient client) { super(client); } @Override public Response load(Uri uri, int networkPolicy) throws IOException { Response responseDiskCache = null; try { responseDiskCache = super.load(uri, 1 << 2); //NetworkPolicy.OFFLINE } catch (Exception ignored){} // ignore, handle null later if (responseDiskCache == null || responseDiskCache.getContentLength()<=0){ return super.load(uri, networkPolicy); //user normal policy } else { return responseDiskCache; } } }

Y en Aplicación singleton en el método OnCreate, úsalo con picasso:

OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.setCache(new Cache(getCacheDir(), 100 * 1024 * 1024)); //100 MB cache, use Integer.MAX_VALUE if it is too low OkHttpDownloader downloader = new OkHttpDownloaderDiskCacheFirst(okHttpClient); Picasso.Builder builder = new Picasso.Builder(this); builder.downloader(downloader); Picasso built = builder.build(); Picasso.setSingletonInstance(built);

3) No se necesitan permisos para la carpeta de caché de la aplicación defalut


Agregue el código siguiente en Application.onCreate luego úselo normalmente

Picasso picasso = new Picasso.Builder(context) .downloader(new OkHttp3Downloader(this,Integer.MAX_VALUE)) .build(); picasso.setIndicatorsEnabled(true); picasso.setLoggingEnabled(true); Picasso.setSingletonInstance(picasso);

Si primero ProductImageDownloader.doBackground en caché las imágenes, haga algo como esto en ProductImageDownloader.doBackground

final Callback callback = new Callback() { @Override public void onSuccess() { downLatch.countDown(); updateProgress(); } @Override public void onError() { errorCount++; downLatch.countDown(); updateProgress(); } }; Picasso.with(context).load(Constants.imagesUrl+productModel.getGalleryImage()) .memoryPolicy(MemoryPolicy.NO_CACHE).fetch(callback); Picasso.with(context).load(Constants.imagesUrl+productModel.getLeftImage()) .memoryPolicy(MemoryPolicy.NO_CACHE).fetch(callback); Picasso.with(context).load(Constants.imagesUrl+productModel.getRightImage()) .memoryPolicy(MemoryPolicy.NO_CACHE).fetch(callback); try { downLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } if(errorCount == 0){ products.remove(productModel); productModel.isDownloaded = true; productsDatasource.updateElseInsert(productModel); }else { //error occurred while downloading images for this product //ignore error for now // FIXME: 9/27/2017 handle error products.remove(productModel); } errorCount = 0; downLatch = new CountDownLatch(3); if(!products.isEmpty() /*&& testCount++ < 30*/){ startDownloading(products.get(0)); }else { //all products with images are downloaded publishProgress(100); }

y cargue sus imágenes como normal o con el almacenamiento en caché de disco

Picasso.with(this).load(Constants.imagesUrl+batterProduct.getGalleryImage()) .networkPolicy(NetworkPolicy.OFFLINE) .placeholder(R.drawable.GalleryDefaultImage) .error(R.drawable.GalleryDefaultImage) .into(viewGallery);

Nota:

El color rojo indica que la imagen se obtiene de la red .

El color verde indica que la imagen se obtiene de la memoria caché .

El color azul indica que la imagen se obtiene de la memoria del disco .

Antes de liberar la aplicación, elimínela o picasso.setLoggingEnabled(true); como false picasso.setLoggingEnabled(true); , picasso.setIndicatorsEnabled(true); si no es requerido Thankx


Esto es lo que hice. Funciona bien.

Primero agregue el OkHttp al archivo de compilación gradle del módulo de la aplicación:

compile ''com.squareup.picasso:picasso:2.5.2'' compile ''com.squareup.okhttp3:okhttp:3.10.0'' compile ''com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0''

Luego haga una Application extensión de clase

import android.app.Application; import com.jakewharton.picasso.OkHttp3Downloader; import com.squareup.picasso.Picasso; public class Global extends Application { @Override public void onCreate() { super.onCreate(); Picasso.Builder builder = new Picasso.Builder(this); builder.downloader(new OkHttp3Downloader(this,Integer.MAX_VALUE)); Picasso built = builder.build(); built.setIndicatorsEnabled(true); built.setLoggingEnabled(true); Picasso.setSingletonInstance(built); } }

agréguelo al archivo Manifiesto de la siguiente manera:

<application android:name=".Global" .. > </application>

Ahora usa Picasso como lo harías normalmente. Sin cambios.

EDITAR:

si solo quieres usar imágenes en caché. Llame a la biblioteca de esta manera. Me he dado cuenta de que si no agregamos NetworkPolicy, las imágenes no se mostrarán en un inicio completamente fuera de línea, incluso si están en caché . El siguiente código resuelve el problema.

Picasso.with(this) .load(url) .networkPolicy(NetworkPolicy.OFFLINE) .into(imageView);

EDIT # 2

El problema con el código anterior es que si borras el caché, Picasso lo seguirá buscando sin conexión en el caché y fallará, el siguiente ejemplo de código examina el caché local, si no se encuentra fuera de línea, se conecta y repone el caché.

Picasso.with(getActivity()) .load(imageUrl) .networkPolicy(NetworkPolicy.OFFLINE) .into(imageView, new Callback() { @Override public void onSuccess() { } @Override public void onError() { //Try again online if cache failed Picasso.with(getActivity()) .load(posts.get(position).getImageUrl()) .error(R.drawable.header) .into(imageView, new Callback() { @Override public void onSuccess() { } @Override public void onError() { Log.v("Picasso","Could not fetch image"); } }); } });


Para el almacenamiento en caché, utilizaría interceptores OkHttp para obtener control sobre la política de almacenamiento en caché. Vea esta muestra que está incluida en la biblioteca OkHttp.

https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/com/squareup/okhttp/recipes/RewriteResponseCacheControl.java

Así es como lo usaría con Picasso:

OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.networkInterceptors().add(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Response originalResponse = chain.proceed(chain.request()); return originalResponse.newBuilder().header("Cache-Control", "max-age=" + (60 * 60 * 24 * 365)).build(); } }); okHttpClient.setCache(new Cache(mainActivity.getCacheDir(), Integer.MAX_VALUE)); OkHttpDownloader okHttpDownloader = new OkHttpDownloader(okHttpClient); Picasso picasso = new Picasso.Builder(mainActivity).downloader(okHttpDownloader).build(); picasso.load(imageURL).into(viewHolder.image);



Uso este código y funcionó, tal vez sea útil para ti:

public static void makeImageRequest(final View parentView,final int id, final String imageUrl) { final int defaultImageResId = R.mipmap.user; final ImageView imageView = (ImageView) parentView.findViewById(id); Picasso.with(context) .load(imageUrl) .networkPolicy(NetworkPolicy.OFFLINE) .into(imageView, new Callback() { @Override public void onSuccess() { Log.v("Picasso","fetch image success in first time."); } @Override public void onError() { //Try again online if cache failed Log.v("Picasso","Could not fetch image in first time..."); Picasso.with(context).load(imageUrl).networkPolicy(NetworkPolicy.NO_CACHE) .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE).error(defaultImageResId) .into(imageView, new Callback() { @Override public void onSuccess() { Log.v("Picasso","fetch image success in try again."); } @Override public void onError() { Log.v("Picasso","Could not fetch image again..."); } }); } }); }


1) respuesta de la primera pregunta: según el método de Picasso Doc for With ()

La instancia global predeterminada de Picasso devuelta desde () se inicializa automáticamente con los valores predeterminados que son adecuados para la mayoría de las implementaciones.

  • Memoria caché LRU del 15% de la RAM de la aplicación disponible
  • Caché de disco de 2% de espacio de almacenamiento de hasta 50 MB pero no menos de 5 MB.

Pero la operación de Disk Cache para Global Default Picasso solo está disponible en API 14+

2) respuesta de la segunda Pregunta: Picasso utiliza la solicitud del cliente HTTP para la operación de Disk Cache Así puede hacer que su propio http request header tenga la propiedad Cache-Control con max-age Cree su propia instancia de Static Picasso en lugar de Picasso predeterminado.

1] HttpResponseCache (Nota: funciona solo para API 13+)
2] OkHttpClient (funciona para todas las API)

Ejemplo para usar OkHttpClient para crear su propia clase Static Picasso:

  • Primero crea una nueva clase para obtener tu propio objeto singleton picasso

    import android.content.Context; import com.squareup.picasso.Downloader; import com.squareup.picasso.OkHttpDownloader; import com.squareup.picasso.Picasso; public class PicassoCache { /** * Static Picasso Instance */ private static Picasso picassoInstance = null; /** * PicassoCache Constructor * * @param context application Context */ private PicassoCache (Context context) { Downloader downloader = new OkHttpDownloader(context, Integer.MAX_VALUE); Picasso.Builder builder = new Picasso.Builder(context); builder.downloader(downloader); picassoInstance = builder.build(); } /** * Get Singleton Picasso Instance * * @param context application Context * @return Picasso instance */ public static Picasso getPicassoInstance (Context context) { if (picassoInstance == null) { new PicassoCache(context); return picassoInstance; } return picassoInstance; } }

  • use su propio objeto singleton picasso lugar de Picasso.With()

PicassoCache.getPicassoInstance(getContext()).load(imagePath).into(imageView)

3) respuesta para la tercera pregunta: no necesita ningún permiso de disco para las operaciones de caché de disco

Referencias : problema de Github sobre el caché de disco , dos preguntas han sido respondidas por @jake-wharton -> Question1 y Question2