简体   繁体   English

连续两次获取相同的图像后,android位图内存不足错误

[英]android bitmap out-of-memory error after getting same image twice in a row

I have a program that is supposed to grab an image from a user's gallery and then display the image in a subsequent activity. 我有一个程序,应该从用户的画廊中抓取图像,然后在后续活动中显示该图像。 As part of my testing, I try to do the operation twice in a row: in ViewImageActivity I click on the button that takes me to the gallery; 作为测试的一部分,我尝试连续执行两次操作:在ViewImageActivity中,单击将我带到图库的按钮;然后单击“确定”。 pick an image; 选择一个图像; then see the image in FriendsActivity. 然后在FriendsActivity中查看图片。 Then I click the back button and repeat the process. 然后,我单击“后退”按钮并重复该过程。 The second time around I always get a ava.lang.OutOfMemoryError . 第二次,我总是得到ava.lang.OutOfMemoryError I am including the error log: 我包括错误日志:

04-26 09:43:57.911: W/dalvikvm(30841): threadid=1: thread exiting with uncaught exception (group=0x40c231f8)
04-26 09:43:57.918: E/AndroidRuntime(30841): FATAL EXCEPTION: main
04-26 09:43:57.918: E/AndroidRuntime(30841): java.lang.OutOfMemoryError
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:299)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:324)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at com.example.game.utils.FileUtils.imageFromGallery(FileUtils.java:87)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at com.example.game.utils.FileUtils.unmarshallBitmap(FileUtils.java:71)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at com.example.game.FriendsActivity.onCreate(FriendsActivity.java:46)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.app.Activity.performCreate(Activity.java:4638)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1051)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1940)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2001)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.app.ActivityThread.access$600(ActivityThread.java:129)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1153)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.os.Handler.dispatchMessage(Handler.java:99)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.os.Looper.loop(Looper.java:137)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at android.app.ActivityThread.main(ActivityThread.java:4516)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at java.lang.reflect.Method.invokeNative(Native Method)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at java.lang.reflect.Method.invoke(Method.java:511)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:558)
04-26 09:43:57.918: E/AndroidRuntime(30841):    at dalvik.system.NativeStart.main(Native Method)
04-26 09:44:00.997: I/Process(30841): Sending signal. PID: 30841 SIG: 9

My program is written like so: 我的程序是这样写的:

ViewImageActivity dispatch intent to get photo from image gallery; ViewImageActivity调度意图从图库获取照片; then onActivityResult calls FriendsActivity. 然后onActivityResult调用FriendsActivity。 FriendsActivity in turn calls FileUtils's static method unmarshallBitmap to get the image for displaying. FriendsActivity依次调用FileUtils的静态方法unmarshallBitmap以获取要显示的图像。 See following snippets: 请参阅以下片段:

ViewImageActivity: ViewImageActivity:

public void dispatchGalleryIntent(View view) {
    Intent gallery = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(gallery, LOAD_IMAGE_REQUEST_CODE);
}

 @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
        if (requestCode == LOAD_IMAGE_REQUEST_CODE) {
            imageUri = data.getData();
        }
        dispatchIntentToFriendsActivity();
    }
}

private void dispatchIntentTo FriendsActivity() {
    Intent intent = new Intent(this, FriendsActivity.class);
    intent.putExtra(IMAGE_URI, imageUri);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(intent);
}

FriendsActivity 好友活动

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_friends);
    Uri imageUri = (Uri) getIntent().getExtras().get(IMAGE_URI);
    myImage = FileUtils.unmarshallBitmap(imageUri, getContentResolver());

      ...
}

FileUtils 文件实用程序

public static Bitmap unmarshallBitmap(Uri imageUri, ContentResolver resolver) {
   return imageFromGallery(imageUri, resolver);
}

private static Bitmap imageFromGallery(Uri imageUri, ContentResolver resolver) {
        try {
            String[] filePathColumn = { MediaStore.Images.Media.DATA };
            Cursor cursor = resolver.query(imageUri, filePathColumn, null, null, null);
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String picturePath = cursor.getString(columnIndex);
            cursor.close();
            return BitmapFactory.decodeFile(picturePath);
        } catch (Exception x) {
            return null;
        }
    }

BTW: I already saw How to solve the Out of Memory issue while displaying image in android? 顺便说一句:我已经看到了在android中显示图像时如何解决内存不足的问题? . My image loads fine the first time. 我的图像第一次加载良好。 The problem is if user change their mind and decide to choose a different image (back button and repeat), then the app crash as explained above. 问题是,如果用户改变主意并决定选择其他图像(返回按钮并重复),则应用程序如上所述崩溃。

当用户按下“后退”按钮并转到其他图像时,回收当前加载的位图图像

myImage.recycle();

You should prepare the image for display by loading it with options.inJustDecodeBounds = true; 您应该通过加载options.inJustDecodeBounds = true来准备要显示的图像。 and then adjusting the samplesize. 然后调整样本大小。

See: http://developer.android.com/training/displaying-bitmaps/ 参见: http : //developer.android.com/training/displaying-bitmaps/

Apart from that, are you calling bitmap.recycle() when you no longer need the bitmap? 除此之外,当您不再需要位图时,是否还要调用bitmap.recycle()? The first could still be in memory when you load the second, causing the error. 加载第二个磁盘时,第一个磁盘可能仍在内存中,从而导致错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM