1

在 ImageSwitcher 中切换图像时,我遇到了一些 OutOfMemory 崩溃,这种情况非常罕见,但有时会发生(对我来说从来没有,否则我可以调试它哈哈)。

我只有 5 张图片 (PNG),每张图片的大小都在 10-60kb 之间,所以说实话我很惊讶。这是代码:

frameImages = new int[]{R.drawable.f_0, R.drawable.f_1, R.drawable.f_2, R.drawable.f_3, R.drawable.f_4};

...
public void switchImage() {
    int frame = getFrame();
    int image = frameImages[frame];

    // imageSwitcher.startAnimation(getAnimation());
    if (frame == 0)
        startYAxisRotation(imageSwitcher, 400);

    imageSwitcher.setImageResource(image); //CRASHES HERE
}

难道我做错了什么?

堆栈跟踪:

java.lang.OutOfMemoryError: 
  at android.graphics.BitmapFactory.nativeDecodeAsset(BitmapFactory.java:0)
  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:677)
  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:507)
  at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:872)
  at android.content.res.Resources.loadDrawable(Resources.java:3022)
  at android.content.res.Resources.getDrawable(Resources.java:1586)
  at android.widget.ImageView.resolveUri(ImageView.java:648)
  at android.widget.ImageView.setImageResource(ImageView.java:377)
  at android.widget.ImageSwitcher.setImageResource(ImageSwitcher.java:41)
  at com.myapp.MainActivity$5.switchImage(MainActivity.java:143)
  at android.os.Handler.handleCallback(Handler.java:733)
  at android.os.Handler.dispatchMessage(Handler.java:95)
  at android.os.Looper.loop(Looper.java:157)
  at android.app.ActivityThread.main(ActivityThread.java:5293)
  at java.lang.reflect.Method.invokeNative(Method.java:0)
  at java.lang.reflect.Method.invoke(Method.java:515)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
  at dalvik.system.NativeStart.main(NativeStart.java:0)
4

4 回答 4

2

使用下面的代码,您可以在将 Bitmap 加载到 ImageSwitcher 之前降低其分辨率。

public void switchImages(){
    //Create a Bitmap with the resolution based on the view size.
    //getWidth and getHeight will not work until the layout as finished,
    //if you need to show an image when the Activity is created you need
    //to follow this link: https://stackoverflow.com/a/6569243/2910520
    Bitmap smallBitmap = decodeSampledBitmapFromResource(getResources(), yourDrawableId, 
                  imageSwitcher.getWidth(), imageSwitcher.getHeight())
    //use a drawable, because you can create it from a custom Bitmap
    BitmapDrawable drawable = new BitmapDrawable(getResources(), smallBitmap);
    imageSwitcher.setImageDrawable(drawable);
}

下面这两种方法是从这里的开发者网站复制而来的

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

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;
}
于 2017-06-10T13:18:19.810 回答
1

不幸的是,如果上述方法均无效,请将其添加到您的清单文件中。内部应用程序标签

 <application
         android:largeHeap="true"


图像加载到位图对象时出现奇怪的内存不足问题

于 2017-06-10T12:31:03.970 回答
0

因此,解决方案是降低图像的分辨率(我在 Photoshop 中手动调整大小)。从 620x1080 到 800x460,一切正常。

结论:图像大小并不那么重要——图像分辨率才是。

PS:MatPag 理论上也应该是正确的,这实际上与我所做的相同 - 除了他在代码中这样做,我自己在 photoshop 中手动完成。但我认为手动这样做更好恕我直言。

于 2017-06-12T06:13:50.413 回答
0

添加 android:largeHeap="true"

在您的清单文件中。

希望能解决你的问题。

于 2017-06-10T12:13:12.557 回答