studio programacion móviles libro imagen desarrollo desarrollar curso atributo aprende aplicaciones android android-recyclerview listadapter picasso okhttp

móviles - manual de programacion android pdf



El adaptador de imagen pierde memoria (2)

La instancia de picasso que se devuelve de PicassoBuilder.build () debe ser un singleton, y cuando necesite usar picasso en toda la aplicación, debe acceder a ese singleton, en lugar de Picasso.with ... debe acceder a

YourClass.getMyPicassoSingleton().with...

De lo contrario, mantendrá cachés separados, etc. para esas instancias de Picasso

editar: como señalo a continuación, también puede llamar

picasso.setSingletonInstance(myPicasso);

justo donde invocas el método de compilación anterior, que también resolvería tu problema sin mantenerte solo. esa es probablemente una solución más limpia

Tengo una simple ListActivity que muestra imágenes e incializo mi OkHttpClient para Picasso Builder en el constructor de la clase ImageAdapter:

picassoClient = new OkHttpClient(); picassoClient.interceptors().add(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request newRequest = chain .request() .newBuilder() .addHeader("Cookie","xyz") .build(); return chain.proceed(newRequest); } }); new Picasso.Builder(context).downloader(new OkHttpDownloader(picassoClient)).build();

luego en getView() uso Picasso para cargar imágenes en ImageView:

Picasso.with(context).load(xyzUrl).fit().centerCrop().into(vImage);

Funciona bien, pero en la rotación del dispositivo veo que el tamaño del montón a veces crece lentamente, a veces rápidamente y a veces permanece estable. Solo raramente cae. ¿Estoy perdiendo memoria o hay algo mal en el código?

EDITAR: getView() este código después de la llamada de Picasso en getView()

if (BuildConfig.DEBUG) { Log.i("HEAP SIZE", String.valueOf((Runtime.getRuntime().totalMemory() / 1024) - (Runtime.getRuntime().freeMemory() / 1024))); }

y descubrí que el crecimiento del tamaño del montón ocurre en getView() después de cargar el mapa de bits en ImageView. ¿Qué está mal?

EDIT 2 : intentado establecer el adaptador de imagen estático, nada cambia

EDIT 3: intentado con RecyclerView en lugar de ListView, el mismo comportamiento: el tamaño del heap crece continuamente mientras se desplaza la lista de imágenes pasando de 30 a 40 bytes en cada onBindViewHolder() . Después de que el tamaño del montón de rotación del dispositivo crece algunas veces incluso 2-3 pasos. Rara vez se cae.

¿Por qué aumentar el tamaño de forma lenta pero continua y por qué estoy filtrando algún caché o algunos mapas de bits en caché después de la rotación del dispositivo?

ACTUALIZACIÓN: adaptador probado sin el código en el constructor (es decir, sin el new OkHttpClient y el new Picasso.Builder ), funciona y el tamaño del new Picasso.Builder dinámico ahora se mantiene estable . Entonces, ¿cuál es la forma correcta de inicializar al cliente con la gestión de encabezados de cookies?

UPSHOT: finalmente creé mi clase PicassoInstance, que crea un único single estático de Picasso y lo configura como singleton de la Biblioteca Picasso. Luego lo configuré en el constructor de mi adaptador

PicassoInstance.setPicassoSingleton(context);

Funciona bien, y es una forma correcta, espero.

public class PicassoInstance { private static Picasso myPicassoInstance = null; public static void setPicassoSingleton(Context context) { if (myPicassoInstance == null) { myPicassoInstance = createMyPicassoInstance(context); Picasso.setSingletonInstance(myPicassoInstance); if (BuildConfig.DEBUG) { Log.i("PICASSO INSTANCE", "CREATED"); } } } private static Picasso createMyPicassoInstance(Context context) { OkHttpClient myOkHttpClient = new OkHttpClient(); myOkHttpClient.interceptors().add(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request newRequest = chain.request().newBuilder() .addHeader("Cookie", "xyz").build(); if (BuildConfig.DEBUG) { Log.i("ON INTERCEPT", "COOKIE ADDED"); } return chain.proceed(newRequest); } }); return new Picasso.Builder(context).downloader( new OkHttpDownloader(myOkHttpClient)).build(); }

}


No puedo cerrarlo como demasiado amplio, pero recomiendo que hayas tomado un volcado de memoria y le hayas dado una mirada dura a Eclipse Memory Analizer Tool para encontrar las referencias que aún se mantienen vivas y por quién.

Este también es un excelente escrito sobre él .

Adaptadores como campos con fugas. Las vistas contienen un contexto que contiene vistas. Y los fragmentos son aún peores ofensores. ListActivities era una herramienta API1 que debería haber quedado obsoleta hace mucho tiempo. Todo muy propenso a fugas, pero esa es la forma de Android.