内容提供者 (获取媒体库图片显示出来)

  • 呈现效果
    • 设计步骤
      • 注意问题

Android 10.0 适配问题都解决了
项目源码.

呈现效果



设计步骤

  1. 第一步:先定义两个Activity,一个获取数据并用来展示,一个展示媒体库图片并提供选择
    MainActivity

     

PackageImageActivity

        
  1. 第二步: Android6.0以后的动态申请权限。

     private void checkReadPermission() {         int readPermission = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);         int writePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);         if (readPermission != PackageManager.PERMISSION_GRANTED && writePermission != PackageManager.PERMISSION_GRANTED) {             requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, READ_PERMISSION_CORD);         }     }    @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {     if (requestCode == READ_PERMISSION_CORD) {         if (grantResults.length == 2 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {             Log.d(TAG, "拥有权限");         }     } }
  2. 第三步 从MainActivity 跳转到 PackageImageActivity

     public void pickImages(View view) {         Intent intent = new Intent(MainActivity.this, PackageImage.class);         startActivity(intent);     }

4. 第四步 使用LoaderManager 异步获取数据

private void initLoaderManager() {        imageItemList.clear();        LoaderManager loaderManager = LoaderManager.getInstance(this);        loaderManager.initLoader(LOADER_ID, null, new LoaderManager.LoaderCallbacks() {            /**             * 因为图库图片可能较多,不能在主线程进行耗时操作             * 在子线程进行操作             * @param id               * @param args             * @return  一个CurSor 装载             */            @NonNull            @Override            public Loader onCreateLoader(int id, @Nullable Bundle args) {            if (id == LOADER_ID) {                return new CursorLoader(PackageImage.this, MediaStore.Images.Media.EXTERNAL_CONTENT_URI,                        new String[]{MediaStore.Images.Media._ID}, null, null, MediaStore.Images.Media.DATE_ADDED+" DESC");            }            return null;        }        /**         * 装载完成后调用         * @param loader   一个对象         * @param cursor   光标,包含所有图片信息。         */        @Override        public void onLoadFinished(@NonNull Loader loader, Cursor cursor) {            if (cursor != null) {                while (cursor.moveToNext()) {                    String id = cursor.getString(0);//                      **因为Android 10.0 以后进行分区存储。我们即使申请权限,也不能访问SD卡的内容。//                      因此如果这里获取path 后面使用Glide 加载图片会报FileNoFOUND错误。所以我们通过ID获取Uri**                        Uri uri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,id);                        imageItemList.add(uri);                        adapter.setData(imageItemList);                    }                }            }        /**         * 重新装载是调用         * @param loader          */        @Override        public void onLoaderReset(@NonNull Loader loader) {        }    });    }
  1. 第五步 使用recyclerView 将获取的图片信息,展现出来

    @NonNull    @Override    public InnerHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_image, parent, false);        //使用该方法,获取屏幕长度,将每一个图片尺寸设置x/3        Point point = SizeUtils.getScreenSize(view.getContext());        RecyclerView.LayoutParams layoutParams = new RecyclerView.LayoutParams(point.x / 3, point.y / 3);        view.setLayoutParams(layoutParams);        return new InnerHolder(view);    }
  2. 第六步 在Adapter 里面暴露一个接口,用于将数据传出来

     public void setOnItemSelectedNum(onItemSelectedNum onItemSelectedNum){         this.mOnItemSelectedNum = onItemSelectedNum;     }      public interface onItemSelectedNum{         void onItemSelectedChange(List list);     }
  3. 第七步 设计事件,用于表示选中图片

     @Override     public void onBindViewHolder(@NonNull InnerHolder holder, int position) {         View view = holder.itemView;         ImageView imageView = view.findViewById(R.id.iv);         final View visibility = view.findViewById(R.id.visibility);         final CheckBox select = view.findViewById(R.id.select);         final Uri uri = mimageItems.get(position);         Glide.with(imageView.getContext()).load(uri).into(imageView); //      先根据状态来渲染,防止紊乱         if (mselect.contains(uri)) {             select.setButtonDrawable(R.drawable.image1);             visibility.setVisibility(View.VISIBLE);         } else {             select.setButtonDrawable(R.drawable.image2);             visibility.setVisibility(View.INVISIBLE);         }          imageView.setOnClickListener(new View.OnClickListener() {             @Override             public void onClick(View v) { //                如果已经没被选择,添加                 if (!mselect.contains(uri)) {                     if(mselect.size()>=9){                         Toast.makeText(select.getContext(),"最多选择"+MAX_SELECTED_PIC+"张图片",Toast.LENGTH_SHORT).show();                      }else{                         mselect.add(uri);                         select.setButtonDrawable(R.drawable.image1);                         visibility.setVisibility(View.VISIBLE);                     }                  } else { //                    如果已经被选择,删除,更改可见度                     mselect.remove(uri);                     select.setButtonDrawable(R.drawable.image2);                     visibility.setVisibility(View.INVISIBLE);                 }                 mOnItemSelectedNum.onItemSelectedChange(mselect);             }         });     }
  4. 第八步 选择完成,将图片传回。需要使前后数据一致。我们使用一个PickerConfig(单例模式) 来实现。 在两个Activity都初始化它

     public class PickerConfig {     //最大选择图片数量     private int max_selected_pic = 1;     private OnItemSelectedFinished monItemSelectedFinished = null;      public OnItemSelectedFinished getMonItemSelectedFinished() {         return monItemSelectedFinished;     }     private PickerConfig(){}     private static PickerConfig pickerConfig;      public static PickerConfig getInstance(){         if(pickerConfig==null){             pickerConfig =new PickerConfig();         }         return pickerConfig;     }      public void setOnItemSelectedFinished(OnItemSelectedFinished onItemSelectedFinished){         this.monItemSelectedFinished = onItemSelectedFinished;     }       public interface OnItemSelectedFinished{         void onItemSelectedFinished(List list);     }      public int getMax_selected_pic() {         return max_selected_pic;     }      public void setMax_selected_pic(int max_selected_pic) {         this.max_selected_pic = max_selected_pic;     } }
  5. 第九步, 两个Activity初始化上面方法。 选择完成 ,数据返回

     public void finishedPic(View view){          //需要获取数据         List list = adapter.getMselect();         //把数据通知给其他地方         PickerConfig.OnItemSelectedFinished monItemSelectedFinished = mpickerConfig.getMonItemSelectedFinished();         if(monItemSelectedFinished!=null){             monItemSelectedFinished.onItemSelectedFinished(list);         }          //结束         finish();     } 
  6. 第十步,将获取的数据在MainActivity 使用recyclView实现。
    可以如果返回图片少于3个,就按几列展示。大于三列的三列显示

    private void initConfig() {        PickerConfig pickerConfig = PickerConfig.getInstance();        pickerConfig.setMax_selected_pic(MAX_SELECTED_PIC);        pickerConfig.setOnItemSelectedFinished(new PickerConfig.OnItemSelectedFinished() {            @Override            public void onItemSelectedFinished(List list) {                int horNum =1;                if(list.size()<3){                    horNum =list.size();                }else{                    horNum =3;                }                GridLayoutManager gridLayoutManager =new GridLayoutManager(MainActivity.this,horNum);                recyclerView.setLayoutManager(gridLayoutManager);                mainAdapter.setData(list,horNum);            }        });    }

注意问题

1. Android10.0 为了保存隐私,不允许访问SD卡的等内容。我们需要使用
MediaStore.Images.Media 得到uri 不能使用path路径
2. Glide4.x 以上版本需要
implementation ‘com.github.bumptech.glide:glide:4.11.0’
annotationProcessor ‘com.github.bumptech.glide:compiler:4.11.0’
并且创建
@GlideModule
public class MyAppGlideModule extends AppGlideModule {
}
4. 如果没有报错,但图片没有加载出来。可能是因为适配器的设置长宽参数不合适

更多相关文章

  1. android避免decodeResource图片时占用太大的内存
  2. MVP模式的Android(安卓)调用系统拍照,相册,剪裁,适配到7.0,修复拍照
  3. Android(安卓)Gradle文件下获取自定义properties文件,并且获取值
  4. 关于SearchView的一些小细节
  5. Glide 在Android(安卓)9.0上不显示图片
  6. android 开机 lanucher
  7. Android中铃声总结【安卓源码解析一】
  8. 居中显示并旋转 android Button 里的属性drawableLeft
  9. input subsystem

随机推荐

  1. Android 自定义CheckBox 样式
  2. 关于CoordinatorLayout展开与折叠相关属
  3. Android中向服务器上传图片
  4. Android Layout_weight 属性
  5. Android(安卓)配置PhoneGap开发环境
  6. Android之-----GridView使用的方法总结
  7. Power Profiling: MQTT on Android (1)
  8. android 闹钟提醒并且在锁屏下弹出Dialog
  9. android:打开Eclipse之后android项目都报
  10. Android(安卓)Handler那些事儿(二)——几个