【问题标题】:external allocation too large for this process此过程的外部分配太大
【发布时间】:2011-11-23 23:52:33
【问题描述】:

我昨晚发布了一个关于这个问题的问题,但我认为我解释得不够好,无法获得适当的帮助。所以基本上,我有一个应用程序,您可以在其中按下一个按钮,让您从图库中选择图像并将其显示在我在应用程序中显示的 ImageView 中。这一切都很好。但是,当我再次按下按钮并选择不同的图片时,应用程序强制关闭。

更新现在,如果我从图库中的下载照片文件夹中拍摄照片,它可以正常工作,可以随意切换照片。但是当我回到我的相机照片文件夹更改图片时,它会强制关闭。

更新 2 它也适用于我的画廊应用程序中的任何其他文件夹。只有一个有这个问题(强制关闭)在“相机”文件夹中

UPDATE 3 19660800 字节的外部分配对于此进程来说太大。导致问题。有什么方法可以减小所选照片的​​大小?

        private static final int SELECT_PICTURE = 1;

      private String selectedImagePath;
      private ImageView img;

      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);

          img = (ImageView)findViewById(R.id.myimageview);

          ((Button) findViewById(R.id.taptoadd))
                  .setOnClickListener(new OnClickListener() {
                      public void onClick(View arg0) {
                          Intent intent = new Intent();
                          intent.setType("image/*");
                          intent.setAction(Intent.ACTION_GET_CONTENT);
                          startActivityForResult(Intent.createChooser(intent,"Select Picture"), SELECT_PICTURE);
                      }
                  });
      }

      public void onActivityResult(int requestCode, int resultCode, Intent data) {
          if (resultCode == RESULT_OK) {
              if (requestCode == SELECT_PICTURE) {
                  Uri selectedImageUri = data.getData();
                  selectedImagePath = getPath(selectedImageUri);
                  System.out.println("Image Path : " + selectedImagePath);
                  img.setImageURI(selectedImageUri);
              }
         }
      }

      public String getPath(Uri uri) {
         String[] projection = { MediaStore.Images.Media.DATA };

          Cursor cursor = managedQuery(uri, projection, null, null, null);
          int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
          cursor.moveToFirst();
          return cursor.getString(column_index);


      }

这是日志

              11-23 16:33:15.871: D/dalvikvm(9171): GC_EXTERNAL_ALLOC freed 51K, 49% free 2793K/5447K, external 20868K/22916K, paused 50ms
    11-23 16:33:15.878: E/dalvikvm-heap(9171): 19660800-byte external allocation too large for this process.
    11-23 16:33:15.886: E/GraphicsJNI(9171): VM won't let us allocate 19660800 bytes
    11-23 16:33:15.906: D/dalvikvm(9171): GC_FOR_MALLOC freed <1K, 49% free 2792K/5447K, external 1668K/20868K, paused 18ms
    11-23 16:33:15.906: D/skia(9171): --- decoder->decode returned false
    11-23 16:33:15.906: D/AndroidRuntime(9171): Shutting down VM
    11-23 16:33:15.910: W/dalvikvm(9171): threadid=1: thread exiting with uncaught exception (group=0x40015560)
    11-23 16:33:15.937: E/AndroidRuntime(9171): FATAL EXCEPTION: main
    11-23 16:33:15.937: E/AndroidRuntime(9171): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.graphics.drawable.Drawable.createFromStream(Drawable.java:657)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.widget.ImageView.resolveUri(ImageView.java:521)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.widget.ImageView.setImageURI(ImageView.java:305)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at snapshot.app.LinearLayoutsActivity.onActivityResult(LinearLayoutsActivity.java:48)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.app.Activity.dispatchActivityResult(Activity.java:3908)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.app.ActivityThread.deliverResults(ActivityThread.java:2528)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.app.ActivityThread.handleSendResult(ActivityThread.java:2574)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.app.ActivityThread.access$2000(ActivityThread.java:117)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:961)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.os.Handler.dispatchMessage(Handler.java:99)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.os.Looper.loop(Looper.java:130)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at android.app.ActivityThread.main(ActivityThread.java:3683)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at java.lang.reflect.Method.invokeNative(Native Method)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at java.lang.reflect.Method.invoke(Method.java:507)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    11-23 16:33:15.937: E/AndroidRuntime(9171):     at dalvik.system.NativeStart.main(Native Method)

【问题讨论】:

  • 应用强制关闭时能否发布 Logcat 输出?
  • 我添加了日志。该应用程序仅在从“相机”文件夹切换照片时强制关闭,所有其他文件夹都可以正常工作。
  • 相机文件夹中的图片似乎太大,导致OOM错误。 Android 的应用只有 16mb 堆。
  • 我该如何解决这个问题?照片是否有缩放意图?

标签: java android imageview gallery


【解决方案1】:

您得到的错误意味着您正在加载的位图太大。您需要对其进行下采样。有关如何处理此问题的一些很好的示例,请参阅此问题:Strange out of memory issue while loading an image to a Bitmap object

更新:您需要先自己加载位图,然后将该位图设置为 ImageView 上的图像,而不是告诉 ImageView 将哪个 URI 作为 Bitmap 加载。这很简单。

要从中加载位图,您必须首先将 URI 转换为包含图像路径的字符串(我认为您可以使用 URI.getPath(),尽管我不确定),然后您可以使用以下方式加载位图:

Bitmap b = BitmapFactory.decodeFile(pathToImage);

这将解码整个位图,而不是您希望将位图下采样到所需的分辨率。假设您的图像视图为 125x125 像素,而您的图像为 1000x1000 像素。 125/1000 = 8 所以我们只需要每 8 个像素解码一次。为此,我们执行以下操作:

int inSample = 8;

opts = new BitmapFactory.Options();
opts.inSampleSize = inSample;

Bitmap b = BitmapFactory.decodeFile(pathToImage, opts); // this bitmap will be 1/8 the size of the original

它非常简单,应该可以解决您的记忆问题。请参阅我对此问题的回答的第二部分:Android GalleryView Recycling 以获得更广泛的解释。

【讨论】:

  • 我这辈子都做不到。 :/(承认 - 我对这一切都很陌生。显然。)
猜你喜欢
  • 2011-09-13
  • 2011-05-10
  • 2012-04-17
  • 1970-01-01
  • 1970-01-01
  • 2012-08-27
  • 1970-01-01
  • 2011-10-04
  • 1970-01-01
相关资源
最近更新 更多