当将inBitmap
设置为true时,我遇到了下一个异常:解码问题造成现有位图无法使用;
出现原因:java.lang.IllegalArgumentException: Problem decoding into existing bitmap
位于android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:460)
...
有趣的是,同样的代码在以下设备上运行时会在不同的位置失败:
- API: 4.4.2, Nexus 4
- API: 4.3.1, Samsung 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);
}
});
}
- 在Nexus 4上,在
// #1
处的BitmapFactory.decodeResource()
崩溃了。 - S3,通过#1显示第一张图片,但在点击图片后在
// #2
的BitmapFactory.decodeResource()
处崩溃。
一些注意点:
- 这些图片大小相同。我尝试过使用
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);
那么这将是垃圾回收的工作:
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
主线程被锁定了100毫秒以上!
如果我没有使用inBitmap
选项对资源进行解码,那么同样的情况也会发生。因此问题仍然存在,如何使用这个属性?
setImageResource()
不好,并且我正在尝试使用inBitmap
标志。 - sromku