当试图从库中加载大图像时崩溃OutOfMemoryError

问题描述:

我试图从大的图库(大约30MB-70MB)加载图像。我一直面临的问题是:当试图从库中加载大图像时崩溃OutOfMemoryError

FATAL EXCEPTION: main Process: com.parse.starter, PID: 29795
java.lang.OutOfMemoryError: Failed to allocate a 1866240012 byte allocation with 2323392 free bytes and 380MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:635) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:611) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:649) at android.provider.MediaStore$Images$Media.getBitmap(MediaStore.java:867) at com.parse.starter.AddPhotosActivity.onActivityResult(AddPhotosActivity.java:151) at android.app.Activity.dispatchActivityResult(Activity.java:6428) at android.app.ActivityThread.deliverResults(ActivityThread.java:3695) at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742) at android.app.ActivityThread.-wrap16(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

这里是我的代码(如上面崩溃日志陈述线151)的正上方的注释。基本上,最终目标是我想立即检测所选图像是否大于10MB。如果是这样,那么发送Toast,如果没有,则继续将图像保存到后端。

if (requestCode == SELECT_PHOTO && resultCode == RESULT_OK) 
{ 
    Uri uri = data.getData(); 
    File f = new File(uri.getPath()); 

    try 
    { 
     // LINE BELOW IS THE LINE 151, ERROR CRASH 
     Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri); 
     if (bitmap.getByteCount() > 10485760) 
     { 
      Toast.makeText(AddPhotosActivity.this, "That file is too large to attach to a Grievance, please try again!", Toast.LENGTH_SHORT).show(); 
     } 
     else 
     { 
      mImageOne.setImageBitmap(bitmap); 
      SaveImageOne(bitmap); 
     } 

    } 
    catch (IOException e) 
    { 
     e.printStackTrace(); 
    } 
} 
+1

BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; 位图bm = BitmapFactory.decodeFile(picPath,options);试试这个 – Nisarg

+1

看到这个:https://developer.android.com/training/displaying-bitmaps/load-bitmap.html – marcinj

+0

请在下次搜索你的例外,有很多问题与此有关 – tyczj

java.lang.OutOfMemoryError发生在图像加载的情况下。因为手机内存有一定的限制。因此,不是直接加载图像,而是使用某种图书馆,如毕加索等,并根据您不需要的大小在原始尺寸加载图像,这将减少内存消耗。

picasso

而更换

mImageOne.setImageBitmap(bitmap); 

Picasso.with(context).load(uri).resize(50, 50).centerCrop().into(mImageOne); 

//这里是50,50新的层面,centercrop是scaletype

+0

谢谢,但这不是我遇到问题的线路。 – Jamie22

+0

你试过这个吗?显然这不是导致问题的那条线。但这是在imageview中加载图像的代码。在调整大小或压缩之前。因此你的手机记忆被填满了。该库不仅用于调整大小,还重用视图以优化内存。你有没有注意到你的logcat。根据它,你的代码没有错误。但是存在导致内存不足异常的代码。 –

你可以用之前测试文件:

File file = new File(uri.getPath()); 

// Get length of file in bytes 
long fileSizeInBytes = file.length(); 

//10485760 will work for your phone, but not for all 
if (fileSizeInMB > 10485760) { 
    ... 
}¸ 

这样你就不必使用太多的内存来改变你的图片 但是内存泄露表明了其他问题。 由于Shahbaz Hashmi说你应该考虑像毕加索,或改变你加载你的形象的方式。

我不知道你想完成什么,但如果你想从画廊或从相机中加载图片请查看本教程:http://www.theappguruz.com/blog/android-take-photo-camera-gallery-code-sample

+0

只需简单地让我的应用程序获取对通过图库选择的图像的引用并将其上传。我没有问题或崩溃,直到我开始选择10MB + – Jamie22

基于问题的投入,好像你首先要检查在处理它之前的文件大小。你可以简单地通过创建一个文件对象,像下面这样做:

File file = new File("<<Provide full file path>>"); 
long length = file.length(); 

if (length > 10485760) 
{ 
      Toast.makeText(AddPhotosActivity.this, "That file is too large to attach to a Grievance, please try again!", Toast.LENGTH_SHORT).show(); 
} 

了解更多关于API在​​

希望这有助于。

干杯!

+0

的图像这是对我最有意义的一个,但我如何从uri获得路径?我尝试过这样的事情,没有运气。 Uri uri = data.getData(); File file = new File(uri.getPath()); – Jamie22

+0

@ Jamie22 - 位于设备上的文件在哪里? –