2010-12-28 7 views
18

안녕하세요 내 응용 프로그램에서 이미지의 경우, 내가 스케일링을 한 경우,하지만 때로는 메모리 예외가 어떻게 나가 메모리를 처리 할 수 ​​있습니다. 예외적으로 효과적이다.안드로이드 메모리 부족 예외 처리하는 방법

+0

OutOfMemory '오류'가 '예외'가 아닙니다. 'Error'와'Excpetion'에는 큰 차이가 있습니다. –

답변

28

로드하기 전에 이미지 크기가 사용 가능한 메모리보다 작은 지 확인하십시오. 따라서 OutOfMemoryException을 처리하는 가장 효율적인 방법은 예외를 피하기 위해 많은 양의 데이터를 메모리에로드하려고 시도하지 않는 방식으로 응용 프로그램을 구조화하는 것입니다.

12

OutOfMemory를 처리 할 수 ​​없습니다. 어떻게 생각해?

장치 메모리가 꽉 차면 예외가 발생하고 마술처럼 예외를 제거하는 무언가를하면 더 많은 힙을 갖게됩니다. 그건 불가능합니다.

OutOfMemory는 발생하지 않도록 처리해야합니다.

+20

이런 소리가 너무 강렬합니다. –

+4

아마 OutOfMemory를 얻는 대부분의 경우 (이 질문에서와 같이) Bitmap 로딩이 포함되어있을 것이고, 아무 것도 없다는 것은 사실이 아닙니다. 할수있다. 많은 경우 N 메가 바이트 이미지를로드 할 수 없지만 여전히 N/4 메가 ​​바이트 이미지를로드 할 수 있습니다. BitmapFactory를 사용하십시오.inSampleSize> = 1 인 옵션과 각 재시도 전에 inSampleSize * = 2를 수행하십시오. –

+19

사실이 게시물은 잘못되었습니다. 장치 메모리가 반드시 가득 찬 것은 아닙니다. OutOfMemory는 요청 된 메모리 양을 할당 할 수 없을 때 발생합니다. 사용 가능한 40MB가 있고 45MB를 할당하려고하면 OutOfMemory가 나오지만 여전히 40MB를 사용할 수 있습니다. – xtempore

8

장치가 메모리 부족 상태 일 때 a method in Activity이 호출되지만 캐시 파일 정리를 트리거하는 데만 사용할 수 있습니다. 그렇다고해서 응용 프로그램 프로세스가 메모리를 초과하지는 않습니다.

오류 또는 OutOfMemoryError를 잡기 위해 try catch 블록을 추가 할 수도 있지만 너무 늦을 수 있습니다.

수많은 비트 맵이나 큰 비트 맵을 처리하는 것은 안드로이드 응용 프로그램에서 실제로 어렵습니다. Romain Guy의이 주제에 대한 팁은 this article에 있습니다.

BitmapFactory.decode *() 메소드에 제공하는 BitmapFactory.options에서 샘플 크기를 지정하여 필요한 해상도로 직접 비트 맵을로드 할 수 있습니다.

+1

onLowMemory는 다른 응용 프로그램이 더 많은 메모리를 필요로 할 때 호출됩니다. 응용 프로그램의 메모리가 부족한 경우가 아닙니다. 따라서 OutOfMemoryError가 발생할 때 onLowMemory가 호출되지 않습니다. – Robert

2

jpeg를 ImageView에로드하고 Out of Memory를 확인하고 적합 할 때까지 크기를 다시 조정하는 루틴을 시도하기 시작했습니다.

static public boolean tryJpegRead(ImageView imageView, File fn){ 
if (!fn.exists()){ 
    Log.d("ANDRO_ASYNC",String.format("missing file %s",fn.getAbsolutePath())); 
    return false; 
} 
BitmapFactory.Options o = new BitmapFactory.Options(); 
    for (int i = 1; i<10; i++){ 
     o.inSampleSize = i; 
     o.inJustDecodeBounds = true; 
     BitmapFactory.decodeFile(fn.getAbsolutePath(), o); 
     int h = o.outHeight; 
     int w = o.outWidth; 
     Log.d("ANDRO_ASYNC",String.format("going in h=%d w=%d resample = %d",h,w,o.inSampleSize)); 
     o.inJustDecodeBounds = false; 
     try{ 
      imageView.setImageBitmap(
       Bitmap.createScaledBitmap(
         BitmapFactory.decodeFile(fn.getAbsolutePath(), o), 
         w, 
         h, 
         true)); 
      return true; // only happens when there is no error 
     }catch(OutOfMemoryError E){ 
      Log.d("ANDRO_ASYNC",String.format("catch Out Of Memory error")); 
    //  E.printStackTrace(); 
      System.gc(); 
     }   
    } 
    return false; 
} 
+0

아이디어가 좋습니다. 대기 시간이 추가됩니까? – drulabs

2

, 조작을 비트 맵 관련에서 OutOfMemory 오류를 처리 디코딩 된 비트 맵의 ​​크기를 확인하는 가장 좋은이며, 지금까지 내가 유일한 방법을 알고있다. 코드는 다음과 같습니다

public static BitmapFactory.Options getBitmapOptionsWithoutDecoding(String url){ 
    BitmapFactory.Options opts = new BitmapFactory.Options(); 
    opts.inJustDecodeBounds = true; 
    BitmapFactory.decodeFile(url, opts); 
    return opts; 
} 

public static int getBitmapSizeWithoutDecoding(String url){ 
    BitmapFactory.Options opts = getBitmapOptionsWithoutDecoding(url); 
    return opts.outHeight*opts.outWidth*32/(1024*1024*8); 
} 

//ref:http://stackoverflow.com/questions/6073744/android-how-to-check-how-much-memory-is-remaining 
public static double availableMemoryMB(){ 
    double max = Runtime.getRuntime().maxMemory()/1024; 
    Debug.MemoryInfo memoryInfo = new Debug.MemoryInfo(); 
    Debug.getMemoryInfo(memoryInfo); 
    return (max - memoryInfo.getTotalPss())/1024; 
} 

public static final long SAFETY_MEMORY_BUFFER = 10;//MB 

public static boolean canBitmapFitInMemory(String path){ 
    long size = getBitmapSizeWithoutDecoding(path); 
    Log.d(TAG, "image MB:"+size); 
    return size <= availableMemoryMB() - SAFETY_MEMORY_BUFFER; 
} 

심판 : 경우 http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

2

당신은 배경 또는 이와 유사한 같은 큰 이미지를 가지고, 메모리 부족 방지하는 쉬운 방법은, 당김-nodpi에 그릴 수-xhdpi에서 이미지를 이동하는 것입니다, 하지만주의를 기울여야 비트 맵이 수정되지 않고로드됩니다. 좋은 방법은 필요

0
try { 
// All methods here.... 
} catch(OutOfMemoryException e){ 
// Show an AlertDialog with "Memory is full" title 
// If press ok then starts the process again.. 
} 
1

사용 안드로이드에 맞게 BitmapFactory.options을 사용해야합니다 allowBackup = "true"로, 안드로이드 : hardwareAccelerated는 = "false"를하고 안드로이드 : largeHeap = "true"로 해결이

<application 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:roundIcon="@mipmap/ic_launcher" 
     android:hardwareAccelerated="false" 
     android:largeHeap="true" 
     android:theme="@style/AppTheme">