2010-12-28 3 views
18

HI В моем приложении у меня есть видеоролики и т. Д., В случае с изображением я сделал масштабирование, но иногда получаю исключение из памяти, как я могу справиться с нехваткой памяти исключение эффективно.android как справиться с недостатком памяти

+0

Это OutOfMemory 'Ошибка', а не' Исключение'. Существует огромная разница между 'Error' и' Excpetion' –

ответ

28

Перед загрузкой убедитесь, что размер изображения меньше, чем доступная память. Таким образом, наиболее эффективным способом обработки OutOfMemoryException является архитектура вашего приложения таким образом, что он никогда не пытается загрузить много данных в память, чтобы избежать исключения.

12

OutOfMemory не может быть обработан. Как вы думаете?

Память устройства заполнена, вы получили исключение, а затем волшебным образом сделаете то, что устранит исключение, и теперь у вас больше кучи. Это невозможно, вы знаете.

OutOfMemory необходимо предотвратить, не обрабатывать после возникновения.

+20

, черт возьми, это звучит так интенсивно –

+4

Вероятно, в большинстве случаев, когда вы получаете OutOfMemory, задействуете загрузку Bitmap (как в этом вопросе), и это просто неправда, что нет ничего, что вы сможет сделать. Во многих случаях вы не можете загрузить изображение N мегабайт, но вы можете загрузить изображение N/4 мегабайта. Используйте BitmapFactory.Параметры с параметром inSampleSize> = 1 и do inSampleSize * = 2 перед каждой попыткой. –

+19

На самом деле это сообщение неверно. Память устройства НЕ обязательно заполнена. OutOfMemory возникает, когда объем запрошенной памяти не может быть выделен. Если доступно 40MB, и вы пытаетесь выделить 45MB, вы получаете OutOfMemory, но у вас все еще есть 40MB. – xtempore

8

Существует a method in Activity, который вызывается, когда устройство достигает минимума памяти, но это может быть использовано только для очистки кеш-файлов. Это не означает, что ваш прикладной процесс выходит из памяти.

Вы также можете добавить блок catch try, чтобы поймать Error или OutOfMemoryError, но это было бы слишком поздно.

Обработка большого количества растровых изображений или больших растровых изображений действительно сложна в приложениях для Android. Вы найдете несколько советов по этому вопросу в this article от Ромена Гая.

Вы также можете позаботиться о загрузке растровых изображений непосредственно в требуемое разрешение, указав размер выборки в BitmapFactory.options, который вы предоставляете методам BitmapFactory.decode *().

+1

Обратите внимание, что onLowMemory вызывается только тогда, когда другому приложению требуется больше памяти. Не когда ваше приложение не работает. Поэтому onLowMemory не будет вызываться при выходе OutOfMemoryError. – 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

В случае, если у вас есть большие изображения, как фон или подобные, простой способ предотвратить Out Of Memory, чтобы перемещать изображения из растяжимого-xhdpi к вытяжке-nodpi, но будьте осторожны, это загрузит растровое изображение без каких-либо изменений. Хороший способ следует использовать BitmapFactory.options, чтобы соответствовать вашей необходимости

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

Использование Android: allowBackup = "истинный", андроид: hardwareAccelerated = "ложь" и андроид: largeHeap = "истина" для решения этой проблемы

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