Android RecyclerView显示图片报错:width and height must be > 0
解决RecyclerView展示图片时的
width and height must be > 0报错 问题原因分析
你遇到的IllegalArgumentException核心原因是:在onBindViewHolder方法中调用image.getWidth()和image.getHeight()时,对应的ImageView还没有完成视图的测量与布局流程,此时它的宽高返回值都是0,而Bitmap.createScaledBitmap要求宽高参数必须大于0,因此触发了报错。
另外还要额外排查一个潜在问题:从数据库读取的字节数组可能为空或者损坏,导致BitmapFactory.decodeByteArray返回null,后续操作也会引发异常。
解决方案
下面提供几种可靠的修复方案,你可以根据需求选择:
方案1:使用ImageView的post方法延迟处理缩放
利用View.post()特性,它会将任务放到视图布局完成后的消息队列中执行,此时就能获取到ImageView的真实宽高:
@Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { holder.listname.setText(String.valueOf(list_name.get(position))); byte[] imageBytes = list_image.get(position); // 先判断字节数组是否有效 if (imageBytes == null || imageBytes.length == 0) { holder.imgname.setImageResource(R.drawable.default_image); // 设置默认图 return; } Bitmap bmp = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); if (bmp == null) { holder.imgname.setImageResource(R.drawable.default_image); // 转Bitmap失败时的默认图 return; } final ImageView imageView = holder.imgname; // 延迟到视图布局完成后执行缩放 imageView.post(new Runnable() { @Override public void run() { int targetWidth = imageView.getWidth(); int targetHeight = imageView.getHeight(); // 再次确认宽高有效(防止极端情况) if (targetWidth > 0 && targetHeight > 0) { Bitmap scaledBitmap = Bitmap.createScaledBitmap(bmp, targetWidth, targetHeight, false); imageView.setImageBitmap(scaledBitmap); // 回收原始Bitmap避免内存泄漏 if (bmp != scaledBitmap) { bmp.recycle(); } } else { imageView.setImageBitmap(bmp); // 宽高仍无效时直接显示原始图 } } }); }
方案2:给ImageView设置固定宽高
在RecyclerView的item布局文件中,给ImageView指定明确的宽高(比如用dp值),这样在onBindViewHolder时就能直接获取到确定的宽高:
<!-- 示例item布局中的ImageView --> <ImageView android:id="@+id/image_list" android:layout_width="100dp" android:layout_height="100dp" android:scaleType="centerCrop" />
这种方式不需要修改太多Java代码,但灵活性较差,适合布局固定的场景。
方案3:使用Glide等图片加载库(推荐)
如果项目中可以引入第三方库,使用Glide这类成熟的图片加载库会更省心,它会自动处理视图布局、Bitmap缩放、内存缓存等问题:
- 先在build.gradle中添加依赖(根据最新版本调整):
implementation 'com.github.bumptech.glide:glide:4.16.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
- 修改
onBindViewHolder代码:
@Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { holder.listname.setText(String.valueOf(list_name.get(position))); byte[] imageBytes = list_image.get(position); if (imageBytes == null || imageBytes.length == 0) { Glide.with(holder.imgname.getContext()) .load(R.drawable.default_image) .into(holder.imgname); return; } Glide.with(holder.imgname.getContext()) .load(imageBytes) .centerCrop() // 可选的缩放类型 .into(holder.imgname); }
额外注意事项
- 从数据库读取Blob时,要确保存储的字节数组是有效的Bitmap数据,避免出现空数组或损坏数据。
- 处理Bitmap时要注意内存泄漏问题,及时回收不再使用的Bitmap对象(如方案1中的
bmp.recycle())。 - 可以给ImageView设置
scaleType属性(比如centerCrop、fitCenter),让图片展示更符合预期。
内容的提问来源于stack exchange,提问作者Kingg
相关产品推荐
相关产品推荐

