You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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缩放、内存缓存等问题:

  1. 先在build.gradle中添加依赖(根据最新版本调整):
implementation 'com.github.bumptech.glide:glide:4.16.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 22:47:46