Ответ 1
Вы не можете увеличить размер кучи динамически, но вы можете запросить больше использовать с помощью.
Android: largeHeap = "истина"
в manifest.xml
, вы можете добавить в свой манифест эти строки, которые он работает для некоторых ситуаций.
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:supportsRtl="true"
android:theme="@style/AppTheme">
Должны ли быть созданы ваши прикладные процессы с большой кучей Dalvik. Это относится ко всем процессам, созданным для приложения. Он применяется только к первому приложению, загружаемому в процесс; если вы используете общий идентификатор пользователя, чтобы разрешить нескольким приложениям использовать процесс, все они должны использовать эту опцию последовательно или у них будут непредсказуемые результаты. Большинство приложений не должны этого нуждаться и вместо этого должны сосредоточиться на сокращении общего использования памяти для повышения производительности. Включение этого также не гарантирует фиксированного увеличения доступной памяти, поскольку некоторые устройства ограничены их общей доступной памятью.
Чтобы запросить доступный размер памяти во время выполнения, используйте методы getMemoryClass()
или getLargeMemoryClass()
.
Если все еще стоит проблема, тогда это также должно работать
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
mBitmapInsurance = BitmapFactory.decodeFile(mCurrentPhotoPath,options);
Это оптимальное использование BitmapFactory.Options.inSampleSize относительно скорости отображения изображения. В документации упоминаются значения, которые имеют мощность 2, поэтому я работаю с 2, 4, 8, 16 и т.д.
Давайте углубимся в выборку изображений:
Например, его не стоит загружать в память изображение с разрешением 1024x768 пикселей, если оно в конечном итоге будет отображаться в миниатюре размером 128 × 128 пикселей в ImageView
.
Чтобы декодер подсуммировал изображение, загрузив меньшую версию в память, установите inSampleSize
в true
в свой BitmapFactory.Options
объект. Например, изображение с разрешением 2100 x 1500 пикселей, декодированное с помощью inSampleSize
of 4, создает растровое изображение размером приблизительно 512x384. Загрузка этого в память использует 0,75 МБ, а не 12 МБ для полного изображения (при условии конфигурации растрового изображения ARGB_8888
). Heres метод для вычисления значения размера выборки, который является мощностью двух на основе ширины и высоты цели:
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
Примечание: вычисляется мощность двух значений, поскольку декодер использует конечное значение, округляя до ближайшей силы двух, согласно
inSampleSize
.
Чтобы использовать этот метод, сначала декодируйте с inJustDecodeBounds
, установленным на true
, передайте параметры через, а затем снова декодируйте, используя новое значение inSampleSize
и inJustDecodeBounds
, установленное на false
:
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
Этот метод упрощает загрузку растрового изображения произвольно большого размера в ImageView
, который отображает миниатюру размером 100x100 пикселей, как показано в следующем примере кода:
mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
Вы можете выполнить аналогичный процесс для декодирования растровых изображений из других источников, заменив соответствующий метод BitmapFactory.decode*
по мере необходимости.
Я нашел этот код интересным:
private Bitmap getBitmap(String path) {
Uri uri = getImageUri(path);
InputStream in = null;
try {
final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
in = mContentResolver.openInputStream(uri);
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, o);
in.close();
int scale = 1;
while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) >
IMAGE_MAX_SIZE) {
scale++;
}
Log.d(TAG, "scale = " + scale + ", orig-width: " + o.outWidth + ",
orig-height: " + o.outHeight);
Bitmap bitmap = null;
in = mContentResolver.openInputStream(uri);
if (scale > 1) {
scale--;
// scale to max possible inSampleSize that still yields an image
// larger than target
o = new BitmapFactory.Options();
o.inSampleSize = scale;
bitmap = BitmapFactory.decodeStream(in, null, o);
// resize to desired dimensions
int height = bitmap.getHeight();
int width = bitmap.getWidth();
Log.d(TAG, "1th scale operation dimenions - width: " + width + ",
height: " + height);
double y = Math.sqrt(IMAGE_MAX_SIZE
/ (((double) width) / height));
double x = (y / height) * width;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int) x,
(int) y, true);
bitmap.recycle();
bitmap = scaledBitmap;
System.gc();
} else {
bitmap = BitmapFactory.decodeStream(in);
}
in.close();
Log.d(TAG, "bitmap size - width: " +bitmap.getWidth() + ", height: " +
bitmap.getHeight());
return bitmap;
} catch (IOException e) {
Log.e(TAG, e.getMessage(),e);
return null;
}
Как управлять памятью приложения: ссылка
Не рекомендуется использовать android:largeHeap="true"
здесь выдержку из Google, которая объясняет это,
Однако способность запрашивать большую кучу предназначена только для небольшой набор приложений, которые могут оправдать необходимость потреблять больше оперативной памяти (например, как большое приложение для редактирования фотографий). Никогда не просите большую кучу просто потому что у вас закончилась нехватка памяти, и вам нужно быстрое исправление - вы должны используйте его только тогда, когда вы точно знаете, где находится вся ваша память и почему он должен быть сохранен. Тем не менее, даже если вы уверены ваше приложение может оправдать большую кучу, вам следует избегать запроса насколько возможно. Использование дополнительной памяти будет все чаще в ущерб общему опыту пользователя, поскольку мусор сбор займет больше времени, а производительность системы может быть медленнее, если переключение задач или выполнение других общих операций.
После работы excrutiatingly с out of memory errors
я бы сказал, добавив это в манифест, чтобы избежать проблемы с oom, не является грехом
Проверка поведения приложения в Android Runtime (ART)
Время выполнения Android (ART) - это среда исполнения по умолчанию для устройств под управлением Android 5.0 (API уровня 21) и выше. Эта среда исполнения предлагает ряд функций, которые повышают производительность и плавность платформы Android и приложений. Вы можете найти дополнительную информацию о новых функциях ART в Представлять ART.
Однако некоторые методы, которые работают на Дальвике, не работают на АРТ. Этот документ позволяет вам узнать о том, что нужно посмотреть при переносе существующего приложения для совместимости с АРТ. Большинство приложений должны работать только при работе с ART.
Проблемы с сборкой мусора (GC)
В Dalvik приложениям часто бывает полезно явно вызвать System.gc(), чтобы вызвать сборку мусора (GC). Это должно быть гораздо менее необходимо для АРТ, особенно если вы вызываете сбор мусора, чтобы предотвратить появление типа GC_FOR_ALLOC или уменьшить фрагментацию. Вы можете проверить, какая среда исполнения используется, вызывая System.getProperty( "java.vm.version" ). Если используется АРТ, значение свойства "2.0.0" или выше.
Кроме того, в Android Open-Source Project (AOSP) разрабатывается компактный сборщик мусора для улучшения управления памятью. Из-за этого вам следует избегать использования методов, которые несовместимы с уплотнением GC (например, сохранение указателей на данные экземпляра объекта). Это особенно важно для приложений, которые используют интерфейс Java Native Interface (JNI). Дополнительные сведения см. В разделе Предупреждение проблем JNI.
Предотвращение проблем JNI
ART JNI несколько более строг, чем у Dalvik's. Особенно полезно использовать режим CheckJNI для обнаружения общих проблем. Если ваше приложение использует код C/С++, вы должны просмотреть следующую статью:
Кроме того, вы можете использовать встроенную память (NDK и JNI), поэтому вы фактически обходите ограничение размера кучи.
Вот несколько сообщений об этом:
-
Операции растрового изображения JNI, чтобы помочь избежать OOM при использовании больших изображений
и здесь создана библиотека для него: