将图像加载到位图对象时出现奇怪的 OutOfMemory 问题 [英] Strange OutOfMemory issue while loading an image to a Bitmap object

查看:32
本文介绍了将图像加载到位图对象时出现奇怪的 OutOfMemory 问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 ListView,每行有几个图像按钮.当用户单击列表行时,它会启动一个新活动.由于相机布局问题,我不得不构建自己的选项卡.为结果启动的活动是地图.如果我点击我的按钮启动图像预览(从 SD 卡加载图像),应用程序从活动返回到 ListView 活动到结果处理程序以重新启动我的新活动,这没什么不仅仅是一个图像小部件.

ListView 上的图像预览是通过光标和 ListAdapter 完成的.这使它变得非常简单,但我不确定如何放置调整大小的图像(即较小的位大小而不是像素作为动态图像按钮的 src.所以我只是调整了图像的大小从手机摄像头上掉下来.

问题是当它尝试返回并重新启动第二个活动时,我收到 OutOfMemoryError.

  • 有没有一种方法可以轻松地逐行构建列表适配器,并且可以动态调整大小(按位)?

这会更可取,因为我还需要对每一行中的小部件/元素的属性进行一些更改,因为由于焦点问题,我无法使用触摸屏选择一行.(我可以使用滚球.)

  • 我知道我可以进行带外调整大小并保存我的图像,但这并不是我真正想要做的,但是一些示例代码会很好.

一旦我在 ListView 上禁用了图像,它又可以正常工作了.

仅供参考:我就是这样做的:

String[] from = new String[] { DBHelper.KEY_BUSINESSNAME, DBHelper.KEY_ADDRESS,DBHelper.KEY_CITY、DBHelper.KEY_GPSLONG、DBHelper.KEY_GPSLAT、DBHelper.KEY_IMAGEFILENAME + ""};int[] to = new int[] { R.id.businessname, R.id.address, R.id.city, R.id.gpslong,R.id.gpslat, R.id.imagefilename };notes = new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);setListAdapter(注释);

其中 R.id.imagefilenameButtonImage.

这是我的 LogCat:

01-25 05:05:49.877: ERROR/dalvikvm-heap(3896): 6291456 字节的外部分配对于这个过程来说太大了.01-25 05:05:49.877:错误/(3896):VM 不会让我们分配 6291456 字节01-25 05:05:49.877:错误/AndroidRuntime(3896):未捕获的处理程序:线程主因未捕获的异常而退出01-25 05:05:49.917:错误/AndroidRuntime(3896):java.lang.OutOfMemoryError:位图大小超出虚拟机预算01-25 05:05:49.917:错误/AndroidRuntime(3896):在android.graphics.BitmapFactory.nativeDecodeStream(本机方法)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:304)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:149)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:174)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.graphics.drawable.Drawable.createFromPath(Drawable.java:729)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.ImageView.resolveUri(ImageView.java:484)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.ImageView.setImageURI(ImageView.java:281)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.SimpleCursorAdapter.setViewImage(SimpleCursorAdapter.java:183)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:129)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.CursorAdapter.getView(CursorAdapter.java:150)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.AbsListView.obtainView(AbsListView.java:1057)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.ListView.makeAndAddView(ListView.java:1616)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.ListView.fillSpecific(ListView.java:1177)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.ListView.layoutChildren(ListView.java:1454)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.AbsListView.onLayout(AbsListView.java:937)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.view.View.layout(View.java:5611)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)01-25 05:05:49.917:错误/AndroidRuntime(3896):在android.widget.LinearLayout.layoutHorizo​​ntal(LinearLayout.java:1108)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.LinearLayout.onLayout(LinearLayout.java:922)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.view.View.layout(View.java:5611)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.FrameLayout.onLayout(FrameLayout.java:294)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.view.View.layout(View.java:5611)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.LinearLayout.layoutVertical(LinearLayout.java:999)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.LinearLayout.onLayout(LinearLayout.java:920)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.view.View.layout(View.java:5611)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.widget.FrameLayout.onLayout(FrameLayout.java:294)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.view.View.layout(View.java:5611)01-25 05:05:49.917:错误/AndroidRuntime(3896):在android.view.ViewRoot.performTraversals(ViewRoot.java:771)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.view.ViewRoot.handleMessage(ViewRoot.java:1103)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.os.Handler.dispatchMessage(Handler.java:88)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.os.Looper.loop(Looper.java:123)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 android.app.ActivityThread.main(ActivityThread.java:3742)01-25 05:05:49.917:错误/AndroidRuntime(3896):在java.lang.reflect.Method.invokeNative(本地方法)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 java.lang.reflect.Method.invoke(Method.java:515)01-25 05:05:49.917: 错误/AndroidRuntime(3896): 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)01-25 05:05:49.917:错误/AndroidRuntime(3896):在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)01-25 05:05:49.917:错误/AndroidRuntime(3896):在dalvik.system.NativeStart.main(本地方法)01-25 05:10:01.127:错误/AndroidRuntime(3943):错误:线程附加失败

我在显示图像时也有一个新错误:

22:13:18.594: DEBUG/skia(4204): xxxxxxxxxxx jpeg error 20 在 %d 状态下对 JPEG 库的调用不当22:13:18.604: INFO/System.out(4204): resolveUri 在坏位图 uri 上失败:22:13:18.694: 错误/dalvikvm-heap(4204): 6291456 字节外部分配对于这个过程来说太大了.22:13:18.694:错误/(4204):VM 不会让我们分配 6291456 字节22:13:18.694:调试/skia(4204):xxxxxxxxxxxxxxxxxxxx allocPixelRef 失败

解决方案

Android 培训 类,有效地显示位图",提供了一些重要信息用于理解和处理异常`java.lang.OutOfMemoryError: bitmap size than VM budgets when loading Bitmaps.


读取位图尺寸和类型

BitmapFactory 类提供了几种解码方法(decodeByteArray()decodeFile()decodeResource()等)用于从各种来源创建 Bitmap.根据您的图像数据源选择最合适的解码方法.这些方法尝试为构造的位图分配内存,因此很容易导致 OutOfMemory 异常.每种类型的解码方法都有额外的签名,让您可以通过 BitmapFactory.Options 类指定解码选项.在解码时将 inJustDecodeBounds 属性设置为 true 可避免内存分配,为位图对象返回 null 但设置 outWidthoutHeightoutMimeType.这种技术允许您在位图的构造(和内存分配)之前读取图像数据的尺寸和类型.

BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeResource(getResources(), R.id.myimage, options);int imageHeight = options.outHeight;int imageWidth = options.outWidth;String imageType = options.outMimeType;

为避免 java.lang.OutOfMemory 异常,请在解码之前检查位图的尺寸,除非您绝对相信该源会为您提供可预测大小且适合可用内存的图像数据.


将缩小版本加载到内存中

既然图像尺寸已知,它们可用于决定是否应将完整图像加载到内存中,或者是否应加载子采样版本.以下是一些需要考虑的因素:

  • 在内存中加载完整图像的估计内存使用量.
  • 考虑到您的应用程序的任何其他内存要求,您愿意承诺加载此图像的内存量.
  • 要加载图像的目标 ImageView 或 UI 组件的尺寸.
  • 当前设备的屏幕尺寸和密度.

例如,如果一个 1024x768 像素的图像最终会在 ImageView 中显示为 128x96 像素的缩略图,那么将其加载到内存中是不值得的.

要告诉解码器对图像进行二次采样,将较小的版本加载到内存中,请在您的 BitmapFactory.Options 对象中将 inSampleSize 设置为 true.例如,分辨率为 2048x1536 的图像以 inSampleSize 为 4 进行解码,生成大约 512x384 的位图.将其加载到内存中使用 0.75MB 而不是完整图像的 12MB(假设位图配置为 ARGB_8888).这是一种根据目标宽度和高度计算样本大小值的方法,该值是 2 的幂:

public static int calculateInSampleSize(BitmapFactory.Options 选项, int reqWidth, int reqHeight) {//图像的原始高度和宽度最终 int 高度 = options.outHeight;最终 int 宽度 = options.outWidth;int inSampleSize = 1;if (height > reqHeight || width > reqWidth) {最终 int halfHeight = 高度/2;最终 int halfWidth = 宽度/2;//计算最大的 inSampleSize 值,它是 2 的幂并保留两者//高度和宽度大于请求的高度和宽度.while ((halfHeight/inSampleSize) > reqHeight&&(halfWidth/inSampleSize) >请求宽度) {样本大小 *= 2;}}返回 inSampleSize;}

<块引用>

注意:计算二值的幂是因为解码器使用最终值通过四舍五入到最接近的二的幂,根据inSampleSize 文档.

要使用此方法,首先将 inJustDecodeBounds 设置为 true 进行解码,传递选项,然后使用新的 inSampleSizevalue 和 inJustDecodeBounds设置为false`:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,int reqWidth, int reqHeight) {//首先使用 inJustDecodeBounds=true 进行解码以检查尺寸final BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeResource(res, resId, options);//计算 inSampleSizeoptions.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);//使用 inSampleSize 设置解码位图options.inJustDecodeBounds = false;返回 BitmapFactory.decodeResource(res, resId, options);}

此方法可以轻松将任意大尺寸的位图加载到显示 100x100 像素缩略图的 ImageView 中,如以下示例代码所示:

mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

您可以按照类似的过程对来自其他来源的位图进行解码,方法是根据需要替换相应的 BitmapFactory.decode* 方法.

I have a ListView with a couple of image buttons on each row. When the user clicks the list row, it launches a new activity. I have had to build my own tabs because of an issue with the camera layout. The activity that gets launched for the result is a map. If I click on my button to launch the image preview (load an image off the SD card) the application returns from the activity back to the ListView activity to the result handler to relaunch my new activity which is nothing more than an image widget.

The image preview on the ListView is being done with the cursor and ListAdapter. This makes it pretty simple, but I am not sure how I can put a resized image (I.e. Smaller bit size not pixel as the src for the image button on the fly. So I just resized the image that came off the phone camera.

The issue is that I get an OutOfMemoryError when it tries to go back and re-launch the 2nd activity.

  • Is there a way I can build the list adapter easily row by row, where I can resize on the fly (bitwise)?

This would be preferable as I also need to make some changes to the properties of the widgets/elements in each row as I am unable to select a row with the touch screen because of the focus issue. (I can use rollerball.)

  • I know I can do an out of band resize and save my image, but that is not really what I want to do, but some sample code for that would be nice.

As soon as I disabled the image on the ListView it worked fine again.

FYI: This is how I was doing it:

String[] from = new String[] { DBHelper.KEY_BUSINESSNAME, DBHelper.KEY_ADDRESS,
    DBHelper.KEY_CITY, DBHelper.KEY_GPSLONG, DBHelper.KEY_GPSLAT,
    DBHelper.KEY_IMAGEFILENAME  + ""};
int[] to = new int[] { R.id.businessname, R.id.address, R.id.city, R.id.gpslong,
    R.id.gpslat, R.id.imagefilename };
notes = new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
setListAdapter(notes);

Where R.id.imagefilename is a ButtonImage.

Here is my LogCat:

01-25 05:05:49.877: ERROR/dalvikvm-heap(3896): 6291456-byte external allocation too large for this process.
01-25 05:05:49.877: ERROR/(3896): VM wont let us allocate 6291456 bytes
01-25 05:05:49.877: ERROR/AndroidRuntime(3896): Uncaught handler: thread main exiting due to uncaught exception
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:304)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:149)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:174)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.drawable.Drawable.createFromPath(Drawable.java:729)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ImageView.resolveUri(ImageView.java:484)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ImageView.setImageURI(ImageView.java:281)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.SimpleCursorAdapter.setViewImage(SimpleCursorAdapter.java:183)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:129)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.CursorAdapter.getView(CursorAdapter.java:150)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.AbsListView.obtainView(AbsListView.java:1057)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ListView.makeAndAddView(ListView.java:1616)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ListView.fillSpecific(ListView.java:1177)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ListView.layoutChildren(ListView.java:1454)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.AbsListView.onLayout(AbsListView.java:937)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1108)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.onLayout(LinearLayout.java:922)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.FrameLayout.onLayout(FrameLayout.java:294)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:999)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.onLayout(LinearLayout.java:920)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.FrameLayout.onLayout(FrameLayout.java:294)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.ViewRoot.performTraversals(ViewRoot.java:771)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1103)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.os.Handler.dispatchMessage(Handler.java:88)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.os.Looper.loop(Looper.java:123)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.app.ActivityThread.main(ActivityThread.java:3742)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at java.lang.reflect.Method.invokeNative(Native Method)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at java.lang.reflect.Method.invoke(Method.java:515)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at dalvik.system.NativeStart.main(Native Method)
01-25 05:10:01.127: ERROR/AndroidRuntime(3943): ERROR: thread attach failed 

I also have a new error when displaying an image:

22:13:18.594: DEBUG/skia(4204): xxxxxxxxxxx jpeg error 20 Improper call to JPEG library in state %d
22:13:18.604: INFO/System.out(4204): resolveUri failed on bad bitmap uri: 
22:13:18.694: ERROR/dalvikvm-heap(4204): 6291456-byte external allocation too large for this process.
22:13:18.694: ERROR/(4204): VM won't let us allocate 6291456 bytes
22:13:18.694: DEBUG/skia(4204): xxxxxxxxxxxxxxxxxxxx allocPixelRef failed

解决方案

The Android Training class, "Displaying Bitmaps Efficiently", offers some great information for understanding and dealing with the exception `java.lang.OutOfMemoryError: bitmap size exceeds VM budget when loading Bitmaps.


Read Bitmap Dimensions and Type

The BitmapFactory class provides several decoding methods (decodeByteArray(), decodeFile(), decodeResource(), etc.) for creating a Bitmap from various sources. Choose the most appropriate decode method based on your image data source. These methods attempt to allocate memory for the constructed bitmap and therefore can easily result in an OutOfMemory exception. Each type of decode method has additional signatures that let you specify decoding options via the BitmapFactory.Options class. Setting the inJustDecodeBounds property to true while decoding avoids memory allocation, returning null for the bitmap object but setting outWidth, outHeight and outMimeType. This technique allows you to read the dimensions and type of the image data prior to the construction (and memory allocation) of the bitmap.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

To avoid java.lang.OutOfMemory exceptions, check the dimensions of a bitmap before decoding it unless you absolutely trust the source to provide you with predictably sized image data that comfortably fits within the available memory.


Load a scaled-down version into Memory

Now that the image dimensions are known, they can be used to decide if the full image should be loaded into memory or if a subsampled version should be loaded instead. Here are some factors to consider:

  • Estimated memory usage of loading the full image in memory.
  • The amount of memory you are willing to commit to loading this image given any other memory requirements of your application.
  • Dimensions of the target ImageView or UI component that the image is to be loaded into.
  • Screen size and density of the current device.

For example, it’s not worth loading a 1024x768 pixel image into memory if it will eventually be displayed in a 128x96 pixel thumbnail in an ImageView.

To tell the decoder to subsample the image, loading a smaller version into memory, set inSampleSize to true in your BitmapFactory.Options object. For example, an image with resolution 2048x1536 that is decoded with an inSampleSize of 4 produces a bitmap of approximately 512x384. Loading this into memory uses 0.75MB rather than 12MB for the full image (assuming a bitmap configuration of ARGB_8888). Here’s a method to calculate a sample size value that is a power of two based on a target width and height:

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

Note: A power of two value is calculated because the decoder uses a final value by rounding down to the nearest power of two, as per the inSampleSize documentation.

To use this method, first decode with inJustDecodeBounds set to true, pass the options through and then decode again using the new inSampleSizevalue andinJustDecodeBoundsset tofalse`:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

This method makes it easy to load a bitmap of arbitrarily large size into an ImageView that displays a 100x100 pixel thumbnail, as shown in the following example code:

mImageView.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

You can follow a similar process to decode bitmaps from other sources, by substituting the appropriate BitmapFactory.decode* method as needed.

这篇关于将图像加载到位图对象时出现奇怪的 OutOfMemory 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆