2011-07-06 4 views
1

해결해야 할 문제는 힙 메모리가 16MB 인 장치에서 발생하는 것으로 알려져 있으며 해결해야합니다. 서버 (큰 이미지)에서 이미지를 가져 오는 스레드가 있고 캐시 된 다음 스레드가 표시됩니다. 문제는 내가 메모리가 부족하다는 것입니다.캐시에서 이미지를 가져 오는 동안 VM의 메모리가 부족합니다.

public class Test extends Activity implements OnClickListener { 
ImageView paint, wheels, shadow; 

Button b; 
int j = 2; 
int i = 1; 
String pathToWheels, pathToPaint, pathToShadow; 
String stringAngle; 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    MemoryInfo dbm = new MemoryInfo(); 
    Debug.getMemoryInfo(dbm); 
    b = (Button) findViewById(R.id.button1); 
    b.setOnClickListener(this); 



    wheels = (ImageView) findViewById(R.id.imageView3); 
    paint = (ImageView) findViewById(R.id.imageView2); 
    shadow = (ImageView) findViewById(R.id.imageView1); 



    while (i < 13) { 

     stringAngle = Integer.toString(i); 
     String pathToWheels = url; 
     String pathToPaint = url; 
     String pathToShadow = url; 

     if (Cache.getCacheFile(pathToWheels) == null) { 
      ImageDownloader downloader1 = new ImageDownloader(wheels); 
      downloader1 
        .execute(url); 
     } else if (Cache.getCacheFile(pathToShadow) == null) { 
      ImageDownloader downloader2 = new ImageDownloader(shadow); 
      downloader2 
        .execute(url); 


     } else if (Cache.getCacheFile(pathToPaint) == null) { 

      ImageDownloader downloader = new ImageDownloader(paint); 
      downloader 
        .execute(url); 


     } 

     i++; 


    } 

} 



@Override 
protected void onPause() { 
    super.onPause(); 
    Toast.makeText(getApplicationContext(),"Pause", 
      Toast.LENGTH_SHORT).show(); 

} 

@Override 
public void onClick(View v) { 


    if (v.getId() == R.id.button1) { 
     if (j == 13) 
     { 
      j = 1; 
     } 
     String s = Integer.toString(j); 
     wheels.setImageBitmap(Cache 
       .getCacheFile(url)); 
     paint.setImageBitmap(Cache 
       .getCacheFile(url)); 
    shadow.setImageBitmap(Cache 
       .getCacheFile(url)); 
     j++; 



    } 
} 

}

내 캐시 클래스 :

: 내 CacheStore 클래스에서

public static void saveCacheFile(String cacheUri, Bitmap image) { 
    if(!isCacheWritable()) return; 
    Log.i("CACHE S",cacheUri); 
    cache.saveCacheFile(cacheUri, image); 

내 로그 고양이를 게시하도록하겠습니다 조금 더뿐만 아니라 몇 가지 코드를 설명하기

public Bitmap getCacheFile(String cacheUri) { 
    if(bitmapMap.containsKey(cacheUri)) return (Bitmap)bitmapMap.get(cacheUri); 

    if(!cacheMap.containsKey(cacheUri)) return null; 
    String fileLocalName = cacheMap.get(cacheUri); 
    File fullCacheDir = new  File(Environment.getExternalStorageDirectory().toString(),cacheDir); 
    File fileUri = new File(fullCacheDir.toString(), fileLocalName); 
    if(!fileUri.exists()) return null; 
    Log.i("CACHE", "File "+cacheUri+" has been found in the Cache"); 
    Bitmap bm = BitmapFactory.decodeFile(fileUri.toString()); 
    Bitmap.createScaledBitmap(bm, 480, 320, true); 
    bitmapMap.put(cacheUri, bm); 
    return bm; 
} 

이 줄에서 앱이 다운됩니다. Bitmap bm = BitmapFactory.decodeFile (fileUri.toString()); 나는 메모리가 부족합니다.

내 로그 캣 : 어떤 도움을 크게 감상 할 수

07-06 23:40:20.720: ERROR/dalvikvm-heap(1844): 691200-byte external allocation too large for this process. 
07-06 23:40:20.720: ERROR/GraphicsJNI(1844): VM won't let us allocate 691200 bytes 
07-06 23:40:20.770: DEBUG/skia(1844): --- decoder->decode returned false 
07-06 23:40:20.790: DEBUG/AndroidRuntime(1844): Shutting down VM 
07-06 23:40:20.830: WARN/dalvikvm(1844): threadid=1: thread exiting with uncaught exception (group=0x4001d800) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844): FATAL EXCEPTION: main 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:459) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:271) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:296) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at com.cache.CacheStore.getCacheFile(CacheStore.java:117) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at com.cache.Cache.getCacheFile(Cache.java:38) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at com.cache.Test.onClick(Test.java:118) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at android.view.View.performClick(View.java:2408) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at android.view.View$PerformClick.run(View.java:8816) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at android.os.Handler.handleCallback(Handler.java:587) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at android.os.Handler.dispatchMessage(Handler.java:92) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at android.os.Looper.loop(Looper.java:123) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at android.app.ActivityThread.main(ActivityThread.java:4627) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at java.lang.reflect.Method.invokeNative(Native Method) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at java.lang.reflect.Method.invoke(Method.java:521) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
07-06 23:40:20.890: ERROR/AndroidRuntime(1844):  at dalvik.system.NativeStart.main(Native Method) 

, 읽어 주셔서 감사합니다.

답변

2

당신은 당신의 imagedownloader 내부 캐시에 삽입에 비트 맵 이전을 샘플을 다시하고 확장해야합니다.

이전에는 이미지를 웹에서 다운로드하기 전에 파일 크기를 감지해야했습니다. 크기가 너무 큰 경우 기본 이미지 만 사용합니다.

또한 BitmapFactory 샘플링 크기를 조정하여 저장된 이미지의 해상도를 낮추고 앱의 최종 이미지 크기를 조정했습니다. (이로 인해 캐시 공간이 많이 절약되었습니다).

이 지금까지 나를 위해 일했다 How to know the size of a file before downloading it?

//somewhere inside image downloader class... 
{...} 

BitmapFactory.Options options = new BitmapFactory.Options(); 

if(enableSampling) 
    options.inSampleSize = 2; 

returnBitmap = BitmapFactory.decodeStream(is, null, options); 

if(returnBitmap != null) 
{ 

    if(scaleImage) 
     returnBitmap = Bitmap.createScaledBitmap(returnBitmap, width, height, true); 

    // insert the image into the cache 
    imageCache.put(url, new SoftReference<Bitmap>(returnBitmap)); 


    // Check the ImageView for nulls 
    if(imageView != null && callback != null){ 
     ImageDisplayer displayer = new ImageDisplayer(imageView, returnBitmap, parentView, tag); 
     callback.onImageReceived(displayer); 
    } 

} 

{...} 

를 참조하고, 미쳐 파일 크기에 대한 검사가 여러 차례에 충돌에서 응용 프로그램을 저장 한, 그것은 단지에 대규모 파일을 downloaing 건너 뛸 수 있습니다 언급하지 않기 배경.

+0

죄송하지만 어디에서 충돌이 발생하는지 편집 해 주셔서 정말 감사드립니다. 또한 EnableSampling 및 scaleImage에 대해 좀 더 노골적으로 표현할 수 있습니까? –

+0

이 두 가지는 그 기능을 즉시 비활성화 할 수있게하려는 부울 값입니다. 이미지가 헤더 파일에서 감지 할 정도로 충분히 작 으면 크기를 조정할 필요가 없지만 다시 샘플링하지 않고 크기를 조정하지 않습니다. –

관련 문제