2012-04-28 2 views
1

이미지를 인터넷에서 단일 활동으로 보여주는 ViewFlipper를 만듭니다. fling 할 때 이미지를 imageView로 설정 한 다음 viewflipper에 추가하십시오. 그러나 OOM은 항상 약 20 개의 이미지를 보여준 후에 발생합니다. 나는 그것을 소홀히하기 위해 깨끗한 일을했는데 제대로 작동하지 않았다! 다음은 코드입니다.메모리 부족으로 인한 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 개 이미지를로드하고 캐시에 보관해야 다른 사람들의 이를 위해 recycle() 기능을 사용하십시오.
원하는 경우 5 개의 이미지를 유지할 수도 있습니다. 그러나 그들을 모두 지킬 필요는 없습니다.

응용 프로그램을 반응 적으로 만들려면 이미지를 x 초 이상 유지하면 전체 이미지를로드하고 메모리에 축소판 그림을 유지하고 표시 할 수 있습니다. 여기

비트 맵

값> 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

귀하의 관심에 감사드립니다, 나는이 문제를 발견했습니다. –

관련 문제