2012-04-28 12 views
1

画像をインターネットで表示するためのViewFlipperを作成しました。 flingを実行するときに、画像をimageViewに設定してからviewflipperに追加します。 しかし、問題は約20枚の画像が表示された後、常にOOMが発生するということです。 私はそれをすすめるためにいくつかのクリーンな仕事をしていたし、それは動作しませんでした! ここにコードがあります。Androidビットマップのメモリ不足でのいくつかの問題

public class ImageCache { 

static private ImageCache cache; 
private Hashtable<Integer, MySoftRef> hashRefs; 
private ReferenceQueue<Bitmap> q; 

private class MySoftRef extends SoftReference<Bitmap> { 
    private Integer _key = 0; 

    public MySoftRef(Bitmap bmp, ReferenceQueue<Bitmap> q, int key) { 
     super(bmp, q); 
     _key = key; 
    } 
} 


public ImageCache() { 
    hashRefs = new Hashtable<Integer, MySoftRef>(); 
    q = new ReferenceQueue<Bitmap>(); 
} 

public static ImageCache getInstance() { 
    if (cache == null) { 
     cache = new ImageCache(); 
    } 
    return cache; 
} 

private void addCacheBitmap(Bitmap bmp, Integer key) { 
    cleanCache(); 
    MySoftRef ref = new MySoftRef(bmp, q, key); 
    hashRefs.put(key, ref); 
} 

public Bitmap getBitmap(int resId) { 
    Bitmap bmp = null; 
    if (hashRefs.containsKey(resId)) { 
     MySoftRef ref = (MySoftRef) hashRefs.get(resId); 
     bmp = (Bitmap) ref.get(); 
    } 

    if (bmp == null) { 
     URL imgUrl = null; 
     try { 
      imgUrl = new URL("http:/example/images/" + resId 
        + ".jpg"); 
      HttpURLConnection conn = (HttpURLConnection) imgUrl 
        .openConnection(); 
      conn.connect(); 
      InputStream is = conn.getInputStream(); 
      bmp = BitmapFactory.decodeStream(is); 
      is.close(); 
      addCacheBitmap(bmp, resId); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 
    return bmp; 
} 

private void cleanCache() { 
    MySoftRef ref = null; 
    while ((ref = (MySoftRef) q.poll()) != null) { 
     hashRefs.remove(ref._key); 
    } 
} 

public void clearCache() { 
    cleanCache(); 
    hashRefs.clear(); 
    System.gc(); 
    System.runFinalization(); 
} 

ここではロードイメージコードです。

public void LoadImage(int n){ 
    iv = new ImageView(this); 
    imageCache = new ImageCache(); 
    Bitmap bm = imageCache.getBitmap(n); 
    iv.setImageBitmap(bm); 
    iv.setScaleType(ImageView.ScaleType.CENTER); 
    viewFlipper.addView(iv, new LayoutParams(LayoutParams.FILL_PARENT, 
      LayoutParams.FILL_PARENT)); 
} 
+0

は、このリンクをチェックしてください... http://developer.android.com/training/displaying-bitmaps/index.htmlあなたの共有のための –

+0

おかげで。それは私にとって助けになる。 –

+0

うん、私のために働いた:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html – Harry

答えて

0

ビットマップで割り当てられたメモリを解放する唯一の方法は、recycle()です。 [current - 1; current + 1]の範囲外にあるremoveView(View)である必要があります。recycle自分で割り当てたビットマップ。そのコードはすべて私にとって過酷に思えますし、GCを呼び出すことも良い考えではありません。永続ストレージにInputStreamの内容を保存して、ネットワークのオーバーヘッドがないようにすることができます。

0

あなただけロードする必要があり、あなたが必要とする3枚の画像キャッシュに保つ:ちょうどメモリを解放

  • 前の画像
  • 現在1
  • 次の1

他のもののそのためにはrecycle()を使用してください。
必要に応じて5枚の画像を保存することもできます。それらをすべて保持する必要はありません。

アプリケーションを反応させたい場合は、サムネイルをメモリに保存して表示し、画像に数秒以上放置すると完全な画像のみを読み込むことができます。ここで

が小さい画像を作成し、> 1の値にビットマップ

Options mThumbOpts = new Options(); 
mThumbOpts.inSampleSize = 4; 

/** The fonction to get a Bitmap from the list */ 
private Bitmap getBitmap(int id) { 
    // TODO recycle previous/next bitmaps here (id -2 and id +2 if they exist) 

    // Reload the image if necessary 
    if (bitmapList[id] == null || bitmapList[id].isRecycled()) { 
     bitmapList[id] = BitmapFactory.decodeFile(imagePath, mThumbOpts); 
    } 
    return bitmapList[id]; 
} 

inSampleSizeセットのリストを管理するためのコードであり、メモリを節約するために小さな画像を返し、元の画像をサブサンプリングするためのデコーダを要求。
より効率的にするには、2の累乗を使用します。本当に不思議です

imageCache = new ImageCache(); 
Bitmap bm = imageCache.getBitmap(n); 

0

はあなたImageCacheクラスのシングルトンの性質を使用していないあなたのコードによると、あなたは毎回LoadImage(int n)が呼ばれる新しいImageCacheインスタンスを作成します。代わりに使用します。

imageCache = ImageCache.getInstance(); 
+0

あなたの注意に感謝し、私はこの問題に気づいた。 –