Android Bitmap压缩不足并导致OutOfMemoryError崩溃

时间:2015-12-22 12:38:16

标签: java android performance android-activity bitmap

我基本上尝试压缩并传递用户选择的图像的Base64表示,但是应用程序在具有OutOfMemoryError问题的不同手机上崩溃。这是我的压缩和转换代码:

Bitmap bm = BitmapFactory.decodeFile(filePath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] byteArrayImage = baos.toByteArray();
String base64String = Base64.encodeToString(byteArrayImage, Base64.DEFAULT);

这个过程也很慢,导致应用程序有时崩溃。

这是我得到的一个例外:

    java.lang.OutOfMemoryError: Failed to allocate a 5035548 byte allocation with 5011320 free bytes and 4MB until OOM
    at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:625)
    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:460)
    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:973)
    at android.content.res.Resources.loadDrawableForCookie(Resources.java:2477)

我应该做出哪些改变?

3 个答案:

答案 0 :(得分:3)

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inSampleSize = 2;  //you can also calculate your inSampleSize
options.inJustDecodeBounds = false;
options.inTempStorage = new byte[16 * 1024];

Bitmap bm = BitmapFactory.decodeFile(filePath,options); //changed line code
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] byteArrayImage = baos.toByteArray();
String base64String = Base64.encodeToString(byteArrayImage, Base64.DEFAULT);

注意:对您的应用程序使用android:largeHeap="true"不被视为理想的解决方案。

以下是Google解压缩的摘录,

  

但是,请求大堆的功能仅适用于a   一小组应用程序,可以证明需要消耗更多的RAM(例如   作为一个大型照片编辑应用程序)。永远不要简单地请求大堆   因为你的内存耗尽,需要快速修复 - 你应该这样做   只有当你确切知道所有记忆的存在时才使用它   分配以及必须保留的原因。然而,即使你有信心   你的应用程序可以证明大堆的合理性,你应该避免请求它   尽可能的。使用额外的内存将越来越多   因为垃圾而损害整体用户体验   收集将花费更长时间,系统性能可能会更慢   任务切换或执行其他常见操作。

这是文档https://developer.android.com/training/articles/memory.html

的完整链接

编辑1:有效缩放图像,例如 WhatsApp图像压缩结帐SO Answer

答案 1 :(得分:0)

尝试使用后回收您的位图。并将位图设置为null。如果你想运行垃圾收集器。

答案 2 :(得分:0)

这种方法对于非常大的图片来说效果不好,比如从相机拍摄的照片。 13 mp的照片是4128x3096x3字节,大约40兆字节。这就是位图的大小。如果您正在动态创建base-64表示,则需要另外40兆字节和更多,因为base-64字符串比可比较的原始字节数组(位图)花费更多的字节存储。

你真的需要把它变成基础64吗?如果您想上传它,可以通过rest api或multipart post request直接进行上传。

如果你不能这样做,也许你可以分割操作,比如每1 MB,或者不是将该字符串写入内存,你可以将其写入文件并在每1 MB操作后附加它?