Picasso: de mémoire

J'ai un RecyclerView présenter plusieurs images à l'aide de Picasso. Après avoir fait défiler un certain temps en haut et en bas de l'application est à court de mémoire avec des messages comme ceci:

E/dalvikvm-heap Out of memory on a 3053072-byte allocation.
I/dalvikvm "Picasso-/wp-content/uploads/2013/12/DSC_0972Small.jpg" prio=5 tid=19 RUNNABLE
I/dalvikvm | group="main" sCount=0 dsCount=0 obj=0x42822a50 self=0x59898998
I/dalvikvm | sysTid=25347 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1500612752
I/dalvikvm | state=R schedstat=( 10373925093 843291977 45448 ) utm=880 stm=157 core=3
I/dalvikvm at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
I/dalvikvm at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
I/dalvikvm at com.squareup.picasso.BitmapHunter.decodeStream(BitmapHunter.java:142)
I/dalvikvm at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:217)
I/dalvikvm at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:159)
I/dalvikvm at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:390)
I/dalvikvm at java.util.concurrent.FutureTask.run(FutureTask.java:234)
I/dalvikvm at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
I/dalvikvm at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
I/dalvikvm at java.lang.Thread.run(Thread.java:841)
I/dalvikvm at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:411)
I/dalvikvm [ 08-10 18:48:35.519 25218:25347 D/skia     ]
--- decoder->decode returned false

Les choses que je remarque en cours de débogage:

  1. Lors de l'installation de l'application sur un téléphone ou un périphérique virtuel, les images sont chargées sur le réseau, ce qui est la façon dont il est censé être. Ceci est perçu par le triangle rouge dans le coin supérieur gauche de l'image.
  2. Lors du défilement de sorte que les images sont rechargées, elles sont lues à partir du disque. Ceci est perçu par le triangle bleu dans le coin supérieur gauche de l'image.
  3. Lors du défilement de plus, certaines images sont chargées à partir de la mémoire, comme on le voit par un triangle vert dans le coin supérieur gauche.
  4. Après le défilement, la mémoire exception se produit et le chargement s'arrête. Seulement l'image d'espace réservé est indiqué sur les images qui ne sont pas actuellement conservé dans la mémoire, alors que ceux de la mémoire sont affichés correctement avec un triangle vert.

Ici est une image de l'échantillon. Il est assez grand, mais je l'utilise fit() à réduire l'empreinte mémoire de l'application.

Donc mes questions sont:

  • Ne pas les images être rechargé à partir du disque lorsque la mémoire cache
    est-il plein?
  • Les images sont tout simplement trop grand? De combien de mémoire puis-je
    s'attendre à une, disons 0,5 MO image, à consommer lors du décodage?
  • Est-il quelque chose de mal ou peu dans mon code ci-dessous?

De la configuration de la statique Picasso exemple lors de la création de la Activity:

private void setupPicasso()
{
Cache diskCache = new Cache(getDir("foo", Context.MODE_PRIVATE), 100000000);
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setCache(diskCache);
Picasso picasso = new Picasso.Builder(this)
.memoryCache(new LruCache(100000000)) //Maybe something fishy here?
.downloader(new OkHttpDownloader(okHttpClient))
.build();
picasso.setIndicatorsEnabled(true); //For debugging
Picasso.setSingletonInstance(picasso);
}

À l'aide de la statique Picasso exemple, dans mon RecyclerView.Adapter:

@Override
public void onBindViewHolder(RecipeViewHolder recipeViewHolder, int position)
{
Picasso.with(mMiasMatActivity)
.load(mRecipes.getImage(position))
.placeholder(R.drawable.picasso_placeholder)
.fit()
.centerCrop()
.into(recipeViewHolder.recipeImage); //recipeImage is an ImageView
//More...
}

La ImageView dans le fichier XML:

<ImageView
android:id="@+id/mm_recipe_item_recipe_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:paddingBottom="2dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:clickable="true"
/>

Mise à jour

Il semble que le défilement de la RecyclerView fait continuellement l'allocation de mémoire s'accroître indéfiniment. J'ai fait un test RecyclerView dépouillé vers le bas pour correspondre à la la documentation officielle, à l'aide d'une seule image pour 200 CardViews avec un ImageView, mais le problème persiste. La plupart des images sont chargées à partir de la mémoire (en vert) et le défilement est fluide, mais sur chaque dixième ImageView de charger l'image à partir du disque (en bleu). Lorsque l'image est chargée à partir d'un disque, d'une allocation de mémoire est effectuée, ainsi, d'augmenter l'allocation sur le tas et donc le segment lui-même.

J'ai essayé de l'enlever de ma propre installation de la global Picasso instance et en utilisant la valeur par défaut à la place, mais les problèmes sont les mêmes.

J'ai fait un contrôle avec l'Appareil Android, Moniteur, voir l'image ci-dessous. C'est pour un Galaxy S3. Chacun des allocations de fait lorsqu'une image est chargé à partir du disque peut être vu à droite, sous "nombre d'allocations par la taille". La taille est légèrement différente pour chaque allocation de l'image, ce qui est aussi bizarre. En appuyant sur "Provoquer GO" rend le plus à droite de l'allocation de 4,7 MO en aller.

Picasso: de mémoire

Le comportement est le même pour les périphériques virtuels. L'image ci-dessous montre pour un Nexus 5 AVD. Ici aussi, la plus grande répartition (10,6 MB) disparaît lorsque vous appuyez sur "Provoquer GO".

Picasso: de mémoire

De plus, voici des images de l'allocation de mémoire les emplacements et les fils de l'Appareil Android Moniteur. La réapparition des allocations sont effectuées dans le Picasso threads alors que l'on a supprimé avec Cause GB est fait sur le thread principal.

Picasso: de mémoire
Picasso: de mémoire

  • Je suis d'avoir exactement le même problème, Même avec seulement 25 recycler les éléments, si j'ai faites défiler vers le haut et vers le bas en permanence il plante avec de la mémoire exception.