您不能动态增加堆大小,但可以通过使用来请求使用更多。
  android:largeHeap =“ true”
在中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堆创建应用程序的进程。这适用于为应用程序创建的所有进程。它仅适用于加载到流程中的第一个应用程序。如果您使用共享用户ID允许多个应用程序使用一个进程,则它们都必须一致地使用此选项,否则它们将产生不可预测的结果。大多数应用程序不需要此,而应专注于减少整体内存使用量以提高性能。启用此功能也不能保证可用内存的固定增加,因为某些设备受到其总可用内存的限制。
要在运行时查询可用内存大小,请使用方法getMemoryClass()或getLargeMemoryClass()。
如果仍然面临问题,那么这也应该起作用
 BitmapFactory.Options options = new BitmapFactory.Options();
 options.inSampleSize = 8;
 mBitmapInsurance = BitmapFactory.decodeFile(mCurrentPhotoPath,options);
如果设置为大于1的值,则请求解码器对原始图像进行二次采样,返回较小的图像以节省内存。
就显示图像的速度而言,这是BitmapFactory.Options.inSampleSize的最佳用法。文档中提到使用的是2的幂的值,因此我正在使用2、4、8、16等。
让我们更深入地了解图像采样:
例如,如果将1024x768像素的图像最终显示在的128x128像素的缩略图中,则不值得将其加载到内存中ImageView。
为了告诉解码器对图像进行二次采样,将较小的版本加载到内存中,inSampleSize并true在您的BitmapFactory.Options对象中将其设置为。例如,以2解码的分辨率为2100 x 1500像素的图像inSampleSize会生成大约512x384的位图。将其加载到内存中需要使用0.75MB而不是12MB的完整图像(假设的位图配置ARGB_8888)。这是一种根据目标宽度和高度计算样本大小值(是2的幂)的方法:
public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    
    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;
        
        
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}
  注意:根据inSampleSize文档,解码器使用四舍五入到最接近的2的幂的最终值来计算2的幂
  。
要使用此方法,请先将inJustDecodeBounds设置为true,然后将选项传递给解码,然后再使用新inSampleSize值inJustDecodeBounds设置为再次解码false:
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {
    
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);
    
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    
    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; 
    in = mContentResolver.openInputStream(uri);
    
    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--;
        
        
        o = new BitmapFactory.Options();
        o.inSampleSize = scale;
        bitmap = BitmapFactory.decodeStream(in, null, o);
        
        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的摘录对此进行解释不是一个好主意,  
  但是,请求大堆的能力仅适用于少数可以证明需要消耗更多RAM的应用程序(例如大型照片编辑应用程序)。切勿仅仅因为内存用完并且需要快速修复而请求大堆-仅在确切知道所有内存的分配位置以及为什么必须保留它时,才应使用它。但是,即使您确信自己的应用程序可以证明大堆的合理性,也应尽可能避免请求它。使用额外的内存将越来越不利于整体用户体验,因为在任务切换或执行其他常见操作时,垃圾回收将花费更长的时间并且系统性能可能会降低。
经过艰苦的工作,out of memory errors我会说将其添加到清单中以避免oom问题不是罪恶
在Android Runtime(ART)上验证应用行为
对于运行Android 5.0(API级别21)及更高版本的设备,Android运行时(ART)是默认运行时。该运行时提供了许多功能,可改善Android平台和应用的性能和流畅性。您可以在“简介”中找到有关ART的新功能的更多信息。
但是,某些在Dalvik上可用的技术不适用于ART。本文档可让您了解在迁移现有应用程序以使其与ART兼容时需要注意的事项。大多数应用程序仅在与ART一起运行时才可以运行。
解决垃圾收集(GC)问题
在Dalvik下,应用程序经常发现显式调用System.gc()来提示垃圾回收(GC)很有用。对于ART,这应该没有必要多得多,尤其是在调用垃圾回收以防止出现GC_FOR_ALLOC类型或减少碎片的情况下。您可以通过调用System.getProperty(“ java.vm.version”)来验证正在使用哪个运行时。如果正在使用ART,则该属性的值为“ 2.0.0”或更高。
此外,Android开源项目(AOSP)中正在开发压缩垃圾收集器,以改善内存管理。因此,您应该避免使用与压缩GC不兼容的技术(例如保存指向对象实例数据的指针)。这对于使用Java本机接口(JNI)的应用程序尤为重要。有关更多信息,请参见防止JNI问题。
防止JNI问题
ART的JNI比Dalvik的JNI更为严格。使用CheckJNI模式来捕获常见问题是一个特别好的主意。如果您的应用程序使用C / C ++代码,则应阅读以下文章:
另外,您可以使用本机内存(NDK和JNI),因此实际上可以绕过堆大小限制。
这是一些有关它的文章:
这是为此而建的图书馆: