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

自定义GridAdapter无法显示应用拍摄的网格图片问题排查求助

安卓网格视图展示拍摄照片问题修复方案

我正在开发一款应用,需要以网格形式展示用户通过应用拍摄的照片。
目前所有配置看起来均无异常,我将对应图片URI保存到URI类型的ArrayList中,再将其传入自定义网格适配器的构造函数。
之后在GridAdapter类中,我会将image_grid_view布局内的ImageView图片设置为从MainActivity获取、已添加到URI ArrayList中的对应URI。

GridAdapter类代码

public class GridAdapter extends BaseAdapter {

    ArrayList<Uri> imagesArrList;
    LayoutInflater inflater;
    Context mContext;

    public GridAdapter(Context _context, ArrayList<Uri> _images) {
        this.mContext = _context;
        this.imagesArrList = _images;
        inflater = LayoutInflater.from(this.mContext);
    }

    @Override
    public int getCount() {
        return imagesArrList.size();
    }

    @Override
    public Object getItem(int position) {
        return imagesArrList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        NewViewHolder mViewHolder;
        Uri image = imagesArrList.get(position);

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.image_grid_view, parent, false);
            mViewHolder = new NewViewHolder(convertView);
            convertView.setTag(mViewHolder);
        } else {
            mViewHolder = (NewViewHolder) convertView.getTag();
        }

        if (image != null) {
            mViewHolder.ivUserImage.setImageURI(image);
        }

        return convertView;
    }

    private static class NewViewHolder {
        ImageView ivUserImage;
        public NewViewHolder(View item) {
            ivUserImage = item.findViewById(R.id.userImage);
        }
    }
}

Main Activity代码

@Override
public void onClick(View view) {
        int id = view.getId();
        if (id == R.id.fab) {
            IMAGE_FILE = UUID.randomUUID().toString() + ".jpg";
            File imageFileReference = createImageFile(IMAGE_FILE);
            Uri imageUri = FileProvider.getUriForFile(this, "--REDACTED FOR PRIVACY---", imageFileReference);
            Log.i("FILEPROVIDERLOG", "File Path: " + imageFileReference.getAbsolutePath());
            Log.i("FILEPROVIDERLOG", "File URI: " + imageUri);
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
            ActivityCompat.startActivityForResult(this, intent, 0, null);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        File imageFileReference = getImageFileReference(IMAGE_FILE);
        Log.i("FILEPROVIDERLOG", "File Path: " + imageFileReference.getAbsolutePath());
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 2;
        Bitmap bitmap = BitmapFactory.decodeFile(imageFileReference.getAbsolutePath());
        iv.setImageBitmap(bitmap);
        Uri imageURI = FileProvider.getUriForFile(this, "--REDACTED FOR PRIVACY---", imageFileReference);
        Log.i("FILEPROVIDERLOG", "File URI: " + imageURI);
        iv.setImageURI(null);
        iv.setImageURI(imageURI);
        imagesArrList.add(imageURI);
        gridView.setAdapter(new GridAdapter(this, imagesArrList));
    }

    private File createImageFile(String _fileName) {
        File imageFile = getImageFileReference(_fileName);
        try{
            imageFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return imageFile;
    }

    private File getImageFileReference(String _fileName) {
        File protectedStorage = getExternalFilesDir(IMAGE_FOLDER);
        return new File(protectedStorage, _fileName);
    }

}

修复方案

  1. 替换图片加载方式
    原生ImageView.setImageURI()仅支持加载小尺寸本地图片,拍照得到的原图分辨率较高,直接加载容易出现加载失败、OOM、卡顿问题,建议使用专业图片加载库处理,例如Glide,引入依赖后将Adapter中setImageURI的逻辑替换为:
Glide.with(mContext)
     .load(image)
     .centerCrop()
     .into(mViewHolder.ivUserImage);
  1. 优化适配器刷新逻辑
    每次新增图片都重新实例化适配器、重新绑定GridView的操作会导致整个列表重绘,性能损耗极大。在Activity初始化阶段仅创建一次适配器并绑定到GridView,后续新增图片后调用notifyDataSetChanged()刷新即可:
  • Activity的onCreate阶段提前初始化:
imagesArrList = new ArrayList<>();
mGridAdapter = new GridAdapter(this, imagesArrList);
gridView.setAdapter(mGridAdapter);
  • onActivityResult中新增图片后替换原有setAdapter逻辑为:
imagesArrList.add(imageURI);
mGridAdapter.notifyDataSetChanged();
  1. 补全URI权限
    当前仅给相机申请了写权限,适配器加载FileProvider生成的URI时缺少读权限也会导致加载失败,给相机Intent新增读权限:
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
  1. 增加拍照结果校验
    当前没有判断拍照返回结果是否成功,用户取消拍照时也会执行后续逻辑会产生无效数据,在onActivityResult最开头增加校验:
if (requestCode == 0 && resultCode == RESULT_OK) {
    // 原有加载、新增图片逻辑放在这里
}

内容的提问来源于stack exchange,提问作者Molag_Bork

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 15:45:02