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

