無限にスクロールすると無限のアイテムが読み込まれる可能性のあるリストビューがあります。
リストビューの各アイテムには、遅延読み込みしている1つまたは2つの画像があります。
すべてがうまく機能しますが、本当に長い間スクロールすると、logcatでこれがクラッシュします
08-07 15:26:25.231: E/AndroidRuntime(30979): FATAL EXCEPTION: Thread-60
08-07 15:26:25.231: E/AndroidRuntime(30979): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
08-07 15:26:25.231: E/AndroidRuntime(30979): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
08-07 15:26:25.231: E/AndroidRuntime(30979): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
08-07 15:26:25.231: E/AndroidRuntime(30979): at com.test.android.helper.LazyImageLoader.decodeFile(LazyImageLoader.java:171)
08-07 15:26:25.231: E/AndroidRuntime(30979): at com.test.android.helper.LazyImageLoader.getBitmap(LazyImageLoader.java:112)
08-07 15:26:25.231: E/AndroidRuntime(30979): at com.test.android.helper.LazyImageLoader.access$2(LazyImageLoader.java:106)
08-07 15:26:25.231: E/AndroidRuntime(30979): at com.test.android.helper.LazyImageLoader$ImageLoader.run(LazyImageLoader.java:197)
私の怠惰な画像ローダーでは、ビットマップをに保存していWeakHashMap
ます。では、ガベージコレクターはビットマップを正しく収集する必要がありますか?
私の怠惰なイメージローダーはこのように動作します。
displayImage()
URLとimageviewへの参照を使用してアダプターから呼び出します
public void displayImage(String url, ImageView imageView, int defaultImageResourceId){
latestImageMetaData.put(imageView, url);
if(weakhashmapcache.containsKey(url)){
imageView.setImageBitmap(weakhashmapcache.get(url));
}
else{
enqueueImage(url, imageView, defaultImageResourceId);
imageView.setImageResource(defaultImageResourceId);
}
}
したがって、キャッシュ内に画像が見つかった場合は、直接設定します。それ以外の場合は、関数を使用してキューに入れますenqueueImage()
。
private void enqueueImage(String url、ImageView imageView、int defaultImageResourceId){Image image = new Image(url、imageView、defaultImageResourceId); downloadqueue.add(image); // downloadQueueは、画像が追加されるのを待つブロッキングキューです//キューがいっぱいになりそうな場合は、キューの先頭にある要素を削除します。これらはとにかく表示されないためですIterator iterator = downloadQueue.iterator(); while(iterator.hasNext()&& downloadQueue.remainingCapacity()<80){downloadQueue.remove(iterator.next()); }}
And my image loader thread is this -
class ImageLoader extends Thread {
public void run() {
Image firstImageInQueue;
try {
while((firstImageInQueue = downloadQueue.take()) != SHUTDOWN_TOKEN)
{
Bitmap imageBitmap = getBitmap(firstImageInQueue.url);
if(imageBitmap != null){
weakhashmap.put(firstImageInQueue.url, imageBitmap);
BitmapDisplayer displayer = new BitmapDisplayer(imageBitmap, firstImageInQueue.imageView, firstImageInQueue.url, firstImageInQueue.defaultImageResourceId);
Activity activity = (Activity)firstImageInQueue.imageView.getContext();
activity.runOnUiThread(displayer);
}
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
finally {
imageLoaderTerminated = true;
}
}
}
getBitmap()
URLスケールから画像をフェッチし、それをビットマップオブジェクトにデコードするだけです。BitmapDisplayer
UIスレッドで画像から画像ビューへの設定を行う単なるRunnableです。
私は何が間違っているのですか?