Cómo utilizar Picasso en el desarrollo de aplicaciones Android
28 February 2014

Si eres desarrollador de aplicaciones para Android, seguro que en algún momento, mientras buscabas alguna librería que te hiciera la vida más fácil, has acabado en la página de square, una de las empresas que más está contribuyendo al mundo opensouce. Entre todas las librerías que tienen publicadas, encontrarás Picasso, uno de los mejores gestores de carga de imágenes que hay disponibles. En iphonedroid, llevamos usando esta librería desde hace bastante tiempo y siempre nos ha funcionado perfectamente. Sin embargo, hace pocos días nos encontramos con que la carga de las imágenes no estaba funcionando como se esperaba. Intentando cargar imágenes en vistas que se inflaban dinámicamente, sorprendentemente la función de callback no siempre se llamaba. El código era algo similar a esto
public void renderImageUrlList(String[] urlList){
mContainer.removeAllViews();
Picasso picasso = Picasso.with(this);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for(String url : urlList) {
//inflate view
TargetTextView tv = (TargetTextView) inflater.inflate(R.layout.my_text_view, null);
mContainer.addView(tv);
tv.setText(url);
//load image
picasso.load(url).into(new MyTarget(tv));
}
}
Como comentaba, la función de callback no se llamaba siempre; no pasaba ni por
onBitmapLoaded
ni por onBitmapFailed
… ¿¡Un problema de carreras!? ¿Qué estaba pasando? Después de depurar y de pegarnos un rato con ello, dimos con la clase Action. Esta clase la usa internamente Picasso para, entre otras cosas, guardar una referencia al Target
que pasamos como parámetro en el método into
. Esta referencia al target se almacena como WeakReference, algo normal para evitar memory leaks, pero que puede tener efectos colaterales si no tenemos claro cómo funciona internamente Picasso. En definitiva, lo que estaba pasando es que cuando la ejecución salía del ámbito de la función donde creaba la instancia del Target
, las WeakReference a estos Target
podrían ser eliminadas por el garbage collector, con lo que Picasso pierde el Target
que habíamos pasado como parámetro. Solución a esto: nunca crees una nueva instancia de Target
cuando llames al método into
. En lugar de esto, implementa el interfaz Target
en tu vista o haz que el Target
sea un miembro de la clase para evitar que el garbage collector elimine la WeakReference.Hemos dejado un proyecto donde podéis ver un ejemplo y reproducir todo esto. Lo podéis descargar aquí.
También podéis encontrar algo de información sobre este problema en este enlace

Deja un comentario