使用BitmapFactory.Options.inBitmap进行位图分配会抛出IllegalArgumentException

sro*_*mku 21 android garbage-collection bitmap bitmapfactory

我得到了下一个异常:当设置为true 时,问题解码到现有位图inBitmap ;

引起:java.lang.IllegalArgumentException:
在android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:460)解码到现有位图时出现问题
...

有趣的是,在运行时,相同的代码在不同的地方失败:

  • API:4.4.2,Nexus 4
  • API:4.3.1,三星s3

这是我的代码,它是这个DevBytes:Bitmap Allocation视频中显示的副本.

private BitmapFactory.Options options;
private Bitmap reusedBitmap;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final ImageView imageView = (ImageView) findViewById(R.id.image_view);

    // set the size to option, the images we will load by using this option
    options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    options.inMutable = true;
    BitmapFactory.decodeResource(getResources(), R.drawable.img1, options);

    // we will create empty bitmap by using the option
    reusedBitmap = Bitmap.createBitmap(options.outWidth, options.outHeight, Bitmap.Config.ARGB_8888);

    // set the option to allocate memory for the bitmap
    options.inJustDecodeBounds = false;
    options.inSampleSize = 1;
    options.inBitmap = reusedBitmap;

    // #1
    reusedBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.img1, options);
    imageView.setImageBitmap(reusedBitmap);

    imageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            options.inBitmap = reusedBitmap;
            // #2
            reusedBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.img2, options);
            imageView.setImageBitmap(reusedBitmap);

        }
    });
}
Run Code Online (Sandbox Code Playgroud)
  • 的Nexus 4,在崩溃BitmapFactory.decodeResource()时// #1
  • S3,传递#1并显示第一个图像,但稍后通过单击at BitmapFactory.decodeResource()处的图像崩溃// #2

几点说明:

  • 图像大小相同.我试着jpg和png.两者都失败了.
  • 位图是可变的.
  • 我canUseForInBitmap按照此处所述使用此方法进行了检查.

题:

如何inBitmap正确使用此属性?

如果你遇到这样的问题,或者你发现我做了些蠢事,请评论/回复.任何帮助将不胜感激.如果你知道任何解决方法,它会很棒.

- 编辑(问题仍然是开放的) -

很抱歉没有解释为什么我试图以这种方式重用位图的原因.
原因是GC每次决定释放内存时都会锁定.
inBitmap功能应该帮助我们重用位图而不分配新的内存,这将导致GC清理已经分配的内存.

例如,如果我使用这种常见方法:

Log.i("my_tag", "image 1");
imageView.setImageResource(R.drawable.img1);
Log.i("my_tag", "image 2");
imageView.setImageResource(R.drawable.img2);
Log.i("my_tag", "image 3");
imageView.setImageResource(R.drawable.img3);
Run Code Online (Sandbox Code Playgroud)

然后这将是GC工作:

I/my_tag  ( 5886): image 1
D/dalvikvm( 5886): GC_FOR_ALLOC freed 91K, 2% free 9113K/9240K, paused 15ms, total 15ms
I/dalvikvm-heap( 5886): Grow heap (frag case) to 19.914MB for 11520016-byte allocation
D/dalvikvm( 5886): GC_FOR_ALLOC freed <1K, 1% free 20362K/20492K, paused 13ms, total 13ms
I/my_tag  ( 5886): image 2
D/dalvikvm( 5886): GC_FOR_ALLOC freed 11252K, 2% free 9111K/9236K, paused 15ms, total 15ms
I/dalvikvm-heap( 5886): Grow heap (frag case) to 19.912MB for 11520016-byte allocation
D/dalvikvm( 5886): GC_FOR_ALLOC freed <1K, 1% free 20361K/20488K, paused 35ms, total 35ms
I/my_tag  ( 5886): image 3
D/dalvikvm( 5886): GC_FOR_ALLOC freed 11250K, 2% free 9111K/9236K, paused 15ms, total 15ms
I/dalvikvm-heap( 5886): Grow heap (frag case) to 19.913MB for 11520016-byte allocation
D/dalvikvm( 5886): GC_FOR_ALLOC freed <1K, 1% free 20361K/20488K, paused 32ms, total 32ms
Run Code Online (Sandbox Code Playgroud)

这是超过100ms的锁定主线程!

如果我decodeResource()没有inBitmap选择,也会发生同样的事情.那么问题仍然是开放的,如何使用这个属性?

hel*_*eye 3

我用模拟的 Nexus 4 尝试了你的代码。
我有默认的 ic_launcher.png 文件,我将其复制并粘贴到drawable-mdpi 中两次(就像我通常做的那样)。我重命名了这两个新文件以匹配代码中的名称(这样我就可以减少需要进行的更改)。
当我运行该应用程序时,我观察到的情况与您相同。
经过几次不同的尝试后,我决定将新的 png 复制到其他可绘制文件夹 - 所以它们存在于:

  • 可绘制的 hdpi
  • 可绘制 mdpi
  • 可绘制xhdpi
  • 可绘制-xxhdpi

我运行该应用程序并且它正在工作!

我不太确定为什么它真的有效,但显然它必须具有正确的屏幕分辨率/密度。