此过程的外部分配太大

2022-01-24 00:00:00 android java gallery imageview

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

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

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

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

 private static final int SELECT_PICTURE = 1;私有字符串 selectedImagePath;私有 ImageView img;公共无效 onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);设置内容视图(R.layout.main);img = (ImageView)findViewById(R.id.myimageview);((按钮)findViewById(R.id.taptoadd)).setOnClickListener(new OnClickListener() {公共无效 onClick(查看 arg0){意图意图 = new Intent();intent.setType("图片/*");意图.setAction(意图.ACTION_GET_CONTENT);startActivityForResult(Intent.createChooser(intent,"选择图片"), 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("图像路径:" + selectedImagePath);img.setImageURI(selectedImageUri);}}}公共字符串getPath(Uri uri){字符串 [] 投影 = { MediaStore.Images.Media.DATA };光标 cursor = managedQuery(uri, projection, null, null, null);int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);cursor.moveToFirst();返回 cursor.getString(column_index);}

这是日志

 11-23 16:33:15.871: D/dalvikvm(9171): GC_EXTERNAL_ALLOC 释放 51K,49% 释放 2793K/5447K,外部 20868K/22916K,暂停 50ms11-23 16:33:15.878: E/dalvikvm-heap(9171): 19660800 字节的外部分配对于这个进程来说太大了.11-23 16:33:15.886: E/GraphicsJNI(9171): VM 不允许我们分配 19660800 字节11-23 16:33:15.906: D/dalvikvm(9171): GC_FOR_MALLOC freed <1K, 49% free 2792K/5447K, external 1668K/20868K, paused 18ms11-23 16:33:15.906: D/skia(9171):---解码器->解码返回假11-23 16:33:15.906: D/AndroidRuntime(9171): 关闭 VM11-23 16:33:15.910: W/dalvikvm(9171): threadid=1: 线程以未捕获的异常退出 (group=0x40015560)11-23 16:33:15.937:E/AndroidRuntime(9171):致命异常:主要11-23 16:33:15.937: E/AndroidRuntime(9171): java.lang.OutOfMemoryError: 位图大小超出 VM 预算11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.graphics.BitmapFactory.nativeDecodeStream(Native Method)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.graphics.drawable.Drawable.createFromStream(Drawable.java:657)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.widget.ImageView.resolveUri(ImageView.java:521)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.widget.ImageView.setImageURI(ImageView.java:305)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 snapshot.app.LinearLayoutsActivity.onActivityResult(LinearLayoutsActivity.java:48)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.app.Activity.dispatchActivityResult(Activity.java:3908)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.app.ActivityThread.deliverResults(ActivityThread.java:2528)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.app.ActivityThread.handleSendResult(ActivityThread.java:2574)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.app.ActivityThread.access$2000(ActivityThread.java:117)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:961)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.os.Handler.dispatchMessage(Handler.java:99)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.os.Looper.loop(Looper.java:130)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 android.app.ActivityThread.main(ActivityThread.java:3683)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 java.lang.reflect.Method.invokeNative(Native Method)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 java.lang.reflect.Method.invoke(Method.java:507)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)11-23 16:33:15.937: E/AndroidRuntime(9171): 在 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)

解决方案

你得到的错误意味着你正在加载的位图太大.您需要对其进行下采样.有关如何处理此问题的一些很好的示例,请参阅此问题:Strange out将图像加载到位图对象时出现内存问题

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

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

位图 b = BitmapFactory.decodeFile(pathToImage);

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

int inSample = 8;opts = new BitmapFactory.Options();opts.inSampleSize = inSample;位图 b = BitmapFactory.decodeFile(pathToImage, opts);//这个位图将是原始大小的 1/8

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

I posted a question last night about this issue, but I dont think I explained it well enough to get the proper help. So basically, I have an application where you can press a button which will let you select an image from your gallery and show it in an ImageView I have displayed in the app. This all works great. However, when I press the button again and choose a different picture the app force closes.

UPDATE Now, if I take a photo from my downloads photo folder in the gallery it works fine, can switch photos as often as I like. But when I go back to my camera photo folder to change the picture it force closes.

UPDATE 2 It also works fine with any other folder I have in my Gallery app. Only one having this problem (force close) is on the "Camera" Folder

UPDATE 3 19660800-byte external allocation too large for this process. is causing the issue. Any ways on reducing the size of the photos being selected?

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


      }

here is the log

              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)

解决方案

The error you are getting means that the bitmap you are loading is too big. You need to downsample it. See this question for some great examples on how to deal with this: Strange out of memory issue while loading an image to a Bitmap object

Update: Instead of telling the ImageView which URI to load as a Bitmap, you need to load the bitmap first yourself and then set that bitmap as the image on the ImageView. This is pretty straightforward.

To load a bitmap from you must first convert the URI to a String (I think you can use URI.getPath() although I'm not sure) that contains the path to the image then you can load the bitmap with:

Bitmap b = BitmapFactory.decodeFile(pathToImage);

This will decode the entire bitmap, instead you want to downsample the bitmap to the desired resolution. Lets say your imageview will be 125x125 pixels and your image is 1000x1000 pixels. 125/1000 = 8 so we only need to decode every 8th pixel. To do this we do the following:

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

Its pretty straight forward and should solve your memory issues. See the 2nd part of my answer to this question: Android GalleryView Recycling for a more extensive explanation.

相关文章