【问题标题】:android bitmap out-of-memory error after getting same image twice in a row连续两次获得相同图像后的android位图内存不足错误
【发布时间】:2013-04-26 17:19:09
【问题描述】:

我有一个程序应该从用户的图库中抓取图像,然后在后续活动中显示该图像。作为测试的一部分,我尝试连续两次执行该操作:在 ViewImageActivity 中单击将我带到画廊的按钮;选择一张图片;然后在 FriendsActivity 中查看图像。然后我单击后退按钮并重复该过程。第二次我总是收到ava.lang.OutOfMemoryError。我包括错误日志:

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

我的程序是这样写的:

ViewImageActivity 调度意图以从图片库中获取照片;然后 onActivityResult 调用 FriendsActivity。 FriendsActivity 依次调用 FileUtils 的静态方法unmarshallBitmap 来获取要显示的图像。参见以下 sn-ps:

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);
}

朋友活动

@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());

      ...
}

文件工具

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;
        }
    }

顺便说一句:我已经看过How to solve the Out of Memory issue while displaying image in android?。我的图像第一次加载良好。问题是如果用户改变主意并决定选择不同的图像(后退按钮并重复),那么应用程序就会崩溃,如上所述。

【问题讨论】:

  • 你应该通过 options.inJustDecodeBounds = true; 加载图像来准备显示。然后调整样本大小 :developer.android.com/training/displaying-bitmaps/… 但除此之外,当您不再需要位图时是否调用 bitmap.recycle() ?当您加载第二个时,第一个可能仍在内存中,从而导致错误。
  • @Matt 除了在 onDestroy 中没有帮助和在 onResume 中抱怨尝试使用回收的位图,我还能在哪里调用 recycle 以使其工作?
  • @Matt 非常感谢您提供的链接。我正在阅读...
  • @Matt,它现在可以工作了:)。您介意在我回复时发表您的评论,以便我可以将此帖子标记为已解决吗?谢谢。

标签: android image android-intent bitmap out-of-memory


【解决方案1】:

当用户按下后退按钮并转到不同的图像时,回收当前加载的位图图像

myImage.recycle();

【讨论】:

  • 我已经在 onDestroy 中尝试过myImage.recycle(); [生效,内存不足];在 onResume [应用程序抱怨尝试使用回收的位图]。
  • 您是否每次都重新创建位图?一旦它被回收,你就不能再使用同一个位图,因为它已经被标记为死了。您可以尝试在 onResume 中执行此操作吗: myImage = FileUtils.unmarshallBitmap(imageUri, getContentResolver());在操作前检查条件为 !isRecycled() 和 != null
【解决方案2】:

您应该通过使用 options.inJustDecodeBounds = true; 加载图像来准备显示。然后调整样本大小。

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

除此之外,当您不再需要位图时,您是否会调用 bitmap.recycle()?当您加载第二个时,第一个可能仍在内存中,从而导致错误。

【讨论】:

    猜你喜欢
    • 2013-01-17
    • 1970-01-01
    • 2013-12-20
    • 1970-01-01
    • 2019-10-14
    • 1970-01-01
    • 2012-07-21
    • 1970-01-01
    • 2011-09-01
    相关资源
    最近更新 更多