画像のダウンロードとキャッシュにアプリでPicassoライブラリの最新バージョン2.4.0を使用しています。サイズがそれぞれ300KB〜400KBの画像が約25〜30枚あります。これは決して大きなものでも重いものでもないと思います。
アプリは正常に実行されていますが、logcatのメモリ割り当てが不足しています。なぜこれが起こっているのか誰かが説明できますか?
GridViewアダプターに画像をロードするためのコード:
Picasso.with(mContext).load(getUrl()).placeholder(R.drawable.placeholder)
.into(viewholder.image);
これが私の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)
元のコードは、画像全体をダウンロードし、画像全体をメモリに読み込んでから、Android ImageView
に合わせて画像を縮小しました。
この場合、メモリ内に完全な画像は必要ありません。ImageView
に近いサイズのものが必要です。
ピカソのfit()
がこれを処理します。 BitmapFactory.Options
でinSampleSize
を使用して、メモリに読み込まれる画像をダウンサンプリングし、ImageView
のサイズ程度の画像を取得して、Androidそこから拡大縮小します。これにより、特に使用しているImageView
の大きさに応じて、各画像のメモリフットプリントが大幅に削減されます。
.fit()で気をつけてください!
デバイスの画面幅をサーバーに送信し、デバイスに適切な画像を提供することにより、サーバーから適切な画像サイズを提供することをお勧めします。このように、touはスケーリングを行う必要はありません。
.fit()に言及すると、他のすべての回答は適切に聞こえます。
ただし、.fitの欠点について言及するのは興味深いと思います。
fit()はターゲットImageViewのサイズを測定し、内部でresize()を使用して画像サイズをImageViewのサイズに縮小します。 fit()について知っておくべきことが2つあります。まず、fit()を呼び出すと、ピカソはImageViewのサイズを測定できるようになるまで待機する必要があるため、画像要求を遅らせることができます。次に、ターゲットとしてImageViewを使用した場合にのみfit()を使用できます(他のターゲットについては後で説明します)。
利点は、画像の品質に影響を与えることなく、画像の解像度が可能な限り低くなることです。解像度が低いと、キャッシュに保持されるデータが少なくなります。これにより、アプリのメモリフットプリントにおける画像の影響を大幅に減らすことができます。要約すると、ロード時間を少し速くするよりもメモリへの影響を少なくしたい場合は、fit()が優れたツールです。
TLDR:
ソース: https://futurestud.io/tutorials/picasso-image-resizing-scaling-and-fit
このようにすべき
Picasso.with(mContext).load(getUrl()).fit().placeholder(R.drawable.placeholder)
.into(viewholder.image);