J'utilise la dernière version 2.4.0 de la bibliothèque Picasso dans mon application pour le téléchargement et la mise en cache des images. Il y a environ 25-30 images de taille 300Ko à 400Ko chacune. Je pense que ce n'est en aucun cas quelque chose de gros ou de lourd.
Même si l'application fonctionne correctement, je n'ai plus d'allocation de mémoire dans mon logcat. Quelqu'un peut-il expliquer pourquoi cela se produit-il?
Code de chargement des images dans l'adaptateur GridView:
Picasso.with(mContext).load(getUrl()).placeholder(R.drawable.placeholder)
.into(viewholder.image);
Voici ma sortie Logcat:
I/dalvikvm-heap(11142): Grow heap (frag case) to 53.860MB for 2720016-byte allocation
I/dalvikvm-heap(11142): Forcing collection of SoftReferences for 3265936-byte allocation
E/dalvikvm-heap(11142): Out of memory on a 3265936-byte allocation.
I/dalvikvm(11142): "Picasso-/images/posters/34.71.jpg" prio=5 tid=18 RUNNABLE
I/dalvikvm(11142): | group="main" sCount=0 dsCount=0 obj=0x4283f248 self=0x60a47830
I/dalvikvm(11142): | sysTid=11196 Nice=10 sched=0/0 cgrp=apps/bg_non_interactive I/dalvikvm(11142): | state=R schedstat=( 2070202497 1858185620 3947 ) utm=172 stm=35 core=3
I/dalvikvm(11142): at Android.graphics.Bitmap.nativeCreate(Native Method)
I/dalvikvm(11142): at Android.graphics.Bitmap.createBitmap(Bitmap.Java:726)
I/dalvikvm(11142): at Android.graphics.Bitmap.createBitmap(Bitmap.Java:703)
I/dalvikvm(11142): at Android.graphics.Bitmap.createBitmap(Bitmap.Java:636)
I/dalvikvm(11142): at com.squareup.picasso.BitmapHunter.transformResult(BitmapHunter.I/dalvikvm(11142): at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.Java:168)
I/dalvikvm(11142): at com.squareup.picasso.BitmapHunter.run(BitmapHunter.Java:111)
I/dalvikvm(11142): at Java.util.concurrent.Executors$RunnableAdapter.call(Executors.Java:390I/dalvikvm(11142): at Java.util.concurrent.FutureTask.run(FutureTask.Java:234)
I/dalvikvm(11142): at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.I/dalvikvm(11142): at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.I/dalvikvm(11142): at Java.lang.Thread.run(Thread.Java:841)
I/dalvikvm(11142): at com.squareup.picasso.Utils$PicassoThread.run(Utils.Java:408)
I/dalvikvm-heap(11142): Forcing collection of SoftReferences for 3265936-byte allocation
E/dalvikvm-heap(11142): Out of memory on a 3265936-byte allocation.
I/dalvikvm(11142): "Picasso-/images/posters/34.71.jpg" prio=5 tid=17 RUNNABLE
I/dalvikvm(11142): | group="main" sCount=0 dsCount=0 obj=0x42841b88 self=0x5ec91f90
I/dalvikvm(11142): | sysTid=11183 Nice=10 sched=0/0 cgrp=apps/bg_non_interactive I/dalvikvm(11142): | state=R schedstat=( 2050467088 1713164574 3713 ) utm=172 stm=32 core=3
I/dalvikvm(11142): at Android.graphics.Bitmap.nativeCreate(Native Method)
I/dalvikvm(11142): at Android.graphics.Bitmap.createBitmap(Bitmap.Java:726)
I/dalvikvm(11142): at Android.graphics.Bitmap.createBitmap(Bitmap.Java:703)
I/dalvikvm(11142): at Android.graphics.Bitmap.createBitmap(Bitmap.Java:636)
I/dalvikvm(11142): at com.squareup.picasso.BitmapHunter.transformResult(BitmapHunter.I/dalvikvm(11142): at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.Java:168)
I/dalvikvm(11142): at com.squareup.picasso.BitmapHunter.run(BitmapHunter.Java:111)
I/dalvikvm(11142): at Java.util.concurrent.Executors$RunnableAdapter.call(Executors.Java:390I/dalvikvm(11142): at Java.util.concurrent.FutureTask.run(FutureTask.Java:234)
I/dalvikvm(11142): at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.I/dalvikvm(11142): at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.I/dalvikvm(11142): at Java.lang.Thread.run(Thread.Java:841)
I/dalvikvm(11142): at com.squareup.picasso.Utils$PicassoThread.run(Utils.Java:408)
Votre code d'origine téléchargeait l'intégralité de l'image, le chargeait dans la mémoire, puis qu'Android réduise l'image pour l'adapter à votre ImageView
.
Dans ce cas, vous n'avez pas besoin de la totalité de l'image en mémoire. Vous avez besoin d'une taille plus proche de celle de la variable ImageView
.
fit()
sur Picasso s'en charge. Il utilise inSampleSize
sur BitmapFactory.Options
pour sous-échantillonner l'image lors de son chargement en mémoire, pour obtenir un résultat de la taille de la ImageView
, permettant ainsi à Android de se mettre à l'échelle. Cela réduira considérablement l'empreinte mémoire de chaque image, en particulier en fonction de la taille de la ImageView
utilisée.
Attention avec .fit ()!
Il est préférable de serveur les tailles d'image correctes à partir du serveur, en envoyant la largeur d'écran du périphérique au serveur et en fournissant la bonne image au périphérique. De cette façon, vous n'avez pas besoin de faire la mise à l'échelle.
Toutes les autres réponses sonne bien en mentionnant .fit ().
Je pense qu'il peut être intéressant de mentionner les inconvénients de .fit:
fit () mesure les dimensions de la ImageView cible et utilise en interne resize () pour réduire la taille de l'image aux dimensions de la ImageView. Il y a deux choses à savoir sur fit (). Tout d’abord, l’appel de fit () peut retarder la demande d’image, car Picasso devra attendre que la taille de la ImageView puisse être mesurée. Deuxièmement, vous pouvez uniquement utiliser fit () avec un ImageView comme cible (nous examinerons d'autres cibles plus tard).
L'avantage est que la résolution de l'image est la plus basse possible, sans affecter sa qualité. Une résolution inférieure signifie moins de données à conserver dans le cache. Cela peut réduire considérablement l'impact des images dans l'empreinte mémoire de votre application. En résumé, si vous préférez un impact mémoire moins important que des temps de chargement un peu plus rapides, fit () est un excellent outil.
TLDR:
Source: https://futurestud.io/tutorials/picasso-image-resizing-scaling-and-fit
Devrait comme ça
Picasso.with(mContext).load(getUrl()).fit().placeholder(R.drawable.placeholder)
.into(viewholder.image);