• Just like last year, it was at the end of the year that I began to think of making up some notes. These are all functions that were completed a long time ago, and now I just want to send them out to record them, which is a shame.

  • I would like to briefly describe the functions of this part. Earlier last year, I made the selection of photo albums, but I was not satisfied with it. But last year’s overtime blocked me and I did not spare any time to improve it. It was not until the middle of this year that some pictures were compressed and optimized in imitation of wechat. Most of the photo album revision functions were completed by LCC, our android elder sister. Here is some of them stolen. Write the album part first. If I have time, I will compress and upload the whole picture to gitHub, but depending on my urine nature, maybe…

(As I expected, the previous paragraph, and the bureau, as well as the most code results come out, the interval is less than a month)

  • Although I try to write as much as I can in the code & write clearly about my comments and what I think when I do the related features;
  • But in practice, when I was thinking about doing as much performance tuning as I could, I actually introduced a couple of intermediate variables to operate on, so it might actually be a little bit confusing to understand;
  • When I wrote the whole performance adjustment, I realized that maybe I made the adjustment more in the hope of giving you a idea for the album part of the data processing.
  • But now I use the way may still have a lot of shortcomings & bugs, so it is right to throw a brick to introduce jade, I hope you can clap a lot of bricks, give a more reliable & logical clearer plan.

Some common operations involved in the whole process (specific usage will not be described) and copied codes are as follows:

  1. RxJava, this part of the main thread operation, in the subsequent picture compression process will also have more functions; Retrofit (subsequent networking portion); Really suggested not to see Rxjava to take a look, really easy to use
  2. RxPermissions Permissions are obtained
  3. Image operation related PhotoView image zoom; Glide
  4. DiffUtil performs local refresh of recycleView to save performance and prevent flicker in refresh process (for example, adding/unselecting an image does not need to use global refresh, just need to refresh the relevant selected function number)
  5. I copied a lot of other people’s code in the camera part, such as in the part about the adaptation in the viewfinder, but I forgot whose original copy, I can’t make the real-name system thank you, I’m sorry. Part of the code of the project was completed by our big sister LCC students, thank you; In Diffutils, as well as local refresh related, refer to reference articles, reference links; Thank you

OK, nonsense said old much, begin the text:

The code has been uploadedgithub

Renderings. Forgive my messy photo album

Slag pictures

1. Write a tool class for loading albums:


/**
 * Created by lcc on 2017/9/26.
 */

public class AlbumHelpler {
    private ContentResolver mResolver;
    private Context context;
    public static String ALBUM_NAME = "Recent photos";
    public static String VIDEO_NAME = "All videos"; private long MIN_PIC_SIZE = 1024 * 20; Private long MAX_VIDEO_SIZE = 15 * 1024 * 1024; private long MAX_VIDEO_SIZE = 15 * 1024 * 1024; // Maximum size of video private String MAX_VIDEO_TIME ="10000"; Private List<AlbumModel> albumsList = new ArrayList<>(); Public AlbumHelpler(Context Context) {this. Context = Context; mResolver = context.getContentResolver(); } /** * get all the photos, as well as the album ** @return
     */
    public List<String> getPics() { List<String> picList = new ArrayList<>(); HashMap<String, AlbumModel> temporary = new HashMap<>(); //returnalbumsList; / / a collection of photos picList Uri mTable = MediaStore. Images. Media. EXTERNAL_CONTENT_URI; ImgSize = string.valueof (MIN_PIC_SIZE); // Limit size of photos String imgSize = string.valueof (MIN_PIC_SIZE); / / photos selected column name on behalf of all the columns of the image file address size time String [] mColumns = {MediaStore. Images. ImageColumns. DATA, MediaStore.Images.ImageColumns.SIZE,MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, MediaStore.Images.ImageColumns.DATE_ADDED}; // Photo filter criteria multipurpose type control size String mSelection ="(" + MediaStore.Images.ImageColumns.MIME_TYPE + "=? or " + MediaStore.Images.ImageColumns.MIME_TYPE + "=? or " + MediaStore.Images.ImageColumns.MIME_TYPE + "=? " + ") AND " + MediaStore.Images.ImageColumns.SIZE + ">?"; // Filter conditional values with? For the three image types, consider reducing String[] mSelectArgs = {"image/jpeg"."image/png"."image/webp", imgSize}; MCursor = mresolver. query(mTable, mColumns, mSelection, mSelectArgs, MediaStore.Images.ImageColumns.DATE_ADDED +" DESC");
        if (null == mCursor || mCursor.getCount() == 0) {
            return picList;
        }
        if(null ! = mCursor && mCursor.getCount() ! = 0) { mCursor.moveToFirst(); AlbumModel album1 = new AlbumModel(ALBUM_NAME, 0, mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA))); albumsList.add(0, album1); //while (mCursor.moveToNext()) {
            for(mCursor.moveToFirst(); ! mCursor.isAfterLast(); mCursor.moveToNext()) { String albumPath = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME)); album1.increaseCount();if(temporary. ContainsKey (albumPath)) {// Add an AlbumModel albumBean = temporary. albumBean.increaseCount(); }elseAlbumModel = new AlbumModel(albumPath, 1, 1) mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA))); albumsList.add(albumBean); temporary.put(albumPath, albumBean); } String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)); picList.add(path); }}if(! mCursor.isClosed()) { mCursor.close(); mCursor = null; }returnpicList; } /** * get a collection of pictures and videos ** @return
     */
    public List<DisplayInfoBean> getPicVideosList<DisplayInfoBean> picVideoList = new ArrayList<>(); Uri mTable = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; ImgSize = string.valueof (MIN_PIC_SIZE); // Limit size of photos String imgSize = string.valueof (MIN_PIC_SIZE); / / photos selected column name String [] mColumns = {MediaStore. Images. ImageColumns. DATA, MediaStore. Images. ImageColumns. The SIZE, MediaStore.Images.ImageColumns.DATE_ADDED}; // The photo filter is String mSelection ="(" + MediaStore.Images.ImageColumns.MIME_TYPE + "=? or " + MediaStore.Images.ImageColumns.MIME_TYPE + "=? or " + MediaStore.Images.ImageColumns.MIME_TYPE + "=?" + ")AND " + MediaStore.Images.ImageColumns.SIZE + ">?"; // Filter conditional values with? Corresponding to String[] mSelectArgs = {"image/jpeg"."image/png"."image/webp", imgSize}; String videoSize = string.valueof (MAX_VIDEO_SIZE); String mSelect = MediaStore.Video.Media.MIME_TYPE +"=? AND " + MediaStore.Video.Media.DURATION + "<? AND " + MediaStore.Video.Media.SIZE + "<?";
        String[] mSelectVideoArgs = {"video/mp4", MAX_VIDEO_TIME, videoSize};
        Cursor mCursor = mResolver.query(mTable, mColumns, mSelection, mSelectArgs, MediaStore.Images.ImageColumns.DATE_ADDED + " DESC");
        if (mCursor == null || mCursor.getCount() == 0) {
            return picVideoList;
        }
        if(mCursor ! = null && mCursor.getCount() ! = 0) {while (mCursor.moveToNext()) {
                String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA));
                String addTime = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.ImageColumns.DATE_ADDED));
                picVideoList.add(new DisplayInfoBean(path, addTime));
            }
        }
        Cursor cursor = mResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, mSelect, mSelectVideoArgs, MediaStore.Video.Media.DATE_ADDED + " DESC");
        if (mCursor == null || mCursor.getCount() == 0) {
            return picVideoList;
        }
        try {
            for(cursor.moveToFirst(); ! cursor.isAfterLast(); cursor.moveToNext()) { String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)); / / path String addTime = cursor. Get String (cursor. GetColumnIndexOrThrow (MediaStore. Video. Media. DATE_ADDED)); picVideoList.add(new DisplayInfoBean(path, addTime)); } } catch (Exception e) { e.printStackTrace(); } finally { cursor.close(); cursor = null; }if(! mCursor.isClosed()) { mCursor.close(); mCursor = null; }returnpicVideoList; } /** ** get all photo albums ** Open all comments are still available, * now is a way to put all photo albums and images on top, save a loop * @return
     */
    public List<AlbumModel> getAlbums() {// List<AlbumModel> albumsList = new ArrayList<>(); // HashMap<String, AlbumModel> temporary = new HashMap<>(); // // Minimum photo size // String imgSize = string.valueof (MIN_PIC_SIZE); // Uri mTable = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; / / / / photos selected column names / / String [] mColumns = {MediaStore. Images. ImageColumns. DATA, MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, MediaStore.Images.ImageColumns.DATE_ADDED}; // String mSelection ="(" + MediaStore.Images.ImageColumns.MIME_TYPE + "=? or " + MediaStore.Images.ImageColumns.MIME_TYPE + "=? or " + MediaStore.Images.ImageColumns.MIME_TYPE + "=? " + ") AND " + MediaStore.Images.ImageColumns.SIZE + ">?";
//        String[] mSelectArgs = {"image/jpeg"."image/png"."image/webp", imgSize}; MCursor = mresolver. query(mTable, mColumns, mSelection, mSelectArgs, MediaStore.Images.ImageColumns.DATE_ADDED +" DESC");
//        if (null == mCursor || mCursor.getCount() == 0) {
//            returnalbumsList; / / / /}if(mCursor ! = null && mCursor.getCount() ! = 0) { // mCursor.moveToFirst(); //// Initialize a AlbumModel // AlbumModel album1 = new AlbumModel(ALBUM_NAME, 0, mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA))); // albumsList.add(0, album1); //for(mCursor.moveToFirst(); ! mCursor.isAfterLast(); mCursor.moveToNext()) { ////while(McUrsor.movetonext ()) {//// address of album // String albumPath = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME)); // album1.increaseCount(); //if(temporary. ContainsKey (albumPath)) {//// add an AlbumModel albumBean = temporary. // albumBean.increaseCount(); / /}else{//// otherwise add an album // AlbumModel albumBean = new AlbumModel(albumPath, 1, mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA))); // albumsList.add(albumBean); // temporary.put(albumPath, albumBean); // // // // // /if(! mCursor.isClosed()) { // mCursor.close(); // mCursor = null; / /}returnalbumsList; } /** * public List<AlbumModel>getVideoAlbumsList<AlbumModel> albumsList = new ArrayList<>(); String videoSize = String.valueOf(MAX_VIDEO_SIZE); String mSelect = MediaStore.Video.Media.MIME_TYPE +"=? AND " + MediaStore.Video.Media.DURATION + "< =? AND " + MediaStore.Video.Media.SIZE + "< =?";
        String[] mSelectVideoArgs = {"video/mp4", MAX_VIDEO_TIME, videoSize}; / / Video album get Cursor Cursor = mResolver. Query (MediaStore. Video. Media. EXTERNAL_CONTENT_URI, null, mSelect, mSelectVideoArgs, MediaStore.Video.Media.DATE_ADDED +" DESC");
        if (null == cursor || cursor.getCount() == 0) {
            return albumsList;
        }
        cursor.moveToFirst();
        AlbumModel VideoAlbum = new AlbumModel(VIDEO_NAME, 0, cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA)));
        albumsList.add(VideoAlbum);
        try {
            for(cursor.moveToFirst(); ! cursor.isAfterLast(); cursor.moveToNext()) { VideoAlbum.increaseCount(); } } catch (Exception e) { e.printStackTrace(); } finally { cursor.close(); cursor = null; }returnalbumsList; } /** * get the photo in the album ** @param albumName * @return*/ public List<String> getAlbumPic(String albumName) { List<String> pics = new ArrayList<>(); Uri mTable = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; ImgSize = string.valueof (MIN_PIC_SIZE); // Limit size of photos String imgSize = string.valueof (MIN_PIC_SIZE); / / photos selected column name String [] mColumns = {MediaStore. Images. ImageColumns. DATA, MediaStore. Images. ImageColumns. The SIZE, MediaStore.Images.ImageColumns.DATE_ADDED}; String mSelection ="(" + MediaStore.Images.ImageColumns.MIME_TYPE + "=? or " + MediaStore.Images.ImageColumns.MIME_TYPE + "=? or " + MediaStore.Images.ImageColumns.MIME_TYPE + "=? " + ")AND " + MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME + "=? AND " + MediaStore.Images.ImageColumns.SIZE + ">?";
        String[] selectArgs = {"image/jpeg"."image/png"."image/webp", albumName, imgSize};
        Cursor mCursor = mResolver.query(mTable, mColumns, mSelection, selectArgs, MediaStore.Images.ImageColumns.DATE_ADDED + " DESC");
        if (mCursor == null || mCursor.getCount() == 0) {
            return pics;
        }
        while (mCursor.moveToNext()) {
            pics.add(mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)));
        }
        if(! mCursor.isClosed()) { mCursor.close(); mCursor = null; }returnpics; } /** * Get all videos */ public List<DisplayInfoBean>getVideos() {
        List<DisplayInfoBean> videoLists = new ArrayList<>();
        String videoSize = String.valueOf(MAX_VIDEO_SIZE);
        String mSelect = MediaStore.Video.Media.MIME_TYPE + "=? AND " + MediaStore.Video.Media.DURATION + "< =? AND " + MediaStore.Video.Media.SIZE + "< =?";
        String[] mSelectArgs = {"video/mp4", MAX_VIDEO_TIME, videoSize};
        Cursor cursor = mResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, mSelect, mSelectArgs, MediaStore.Video.Media.DATE_ADDED + " DESC");
        if (null == cursor || cursor.getCount() == 0) {
            return videoLists;
        }
        try {
            for(cursor.moveToFirst(); ! cursor.isAfterLast(); cursor.moveToNext()) { String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)); / / path String addTime = cursor. Get String (cursor. GetColumnIndexOrThrow (MediaStore. Video. Media. DURATION)); videoLists.add(new DisplayInfoBean(path, addTime)); } } catch (Exception e) { e.printStackTrace(); } finally { cursor.close(); cursor = null; }returnvideoLists; }}Copy the code

In fact, also very simple, according to the Cursor for the entire mobile phone picture search. GetAlbums is now used as a Cursor to retrieve all images and albums, but the code is still usable.

2. PhotoSelectorHelper:

Because the above image traversal needs to read local storage, rXJava is used for thread control. Create is the worker thread, and then it reads the data and sends it to SUBSCRIBE, which is the UI thread. When the image is finished, it calls back and back in interface mode.

public class PhotoSelectorHelper { private AlbumHelpler albumController; public PhotoSelectorHelper(Context context) { albumController = new AlbumHelpler(context); } @param listener */ public void getReccentPhotoList(final OnLoadPhotoListener Listener) { Observable.create(new Observable.OnSubscribe<List<String>>() { @Override public void call(Subscriber<? super List<String>> subscriber) { List<String> picVideos = new ArrayList<String>(); List<DisplayInfoBean> photos = albumController.getPicVideos(); Collections.sort(photos, new Comparator<DisplayInfoBean>() { @Override public int compare(DisplayInfoBean o1, DisplayInfoBean o2) {return(int) (Long.parseLong(o2.getAddTime()) - Long.parseLong(o1.getAddTime())); }});for (int i = 0; i < photos.size(); i++) {
                    picVideos.add(photos.get(i).getPath());
                }
                subscriber.onNext(picVideos);
                subscriber.onCompleted();
            }
        }).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())
        .subscribe(
                new Subscriber<List<String>>() {
                    @Override
                    public void onCompleted() { } @Override public void onError(Throwable e) { listener.onPhotoLoaded(new ArrayList<String>()); } @Override public void onNext(List<String> list) { listener.onPhotoLoaded(list); }}); } public void getAllPics(final OnLoadPhotoListener listener) {Observable. Create (new) Observable.OnSubscribe<List<String>>() { @Override public void call(Subscriber<? super List<String>> subscriber) { List<String> list = albumController.getPics(); subscriber.onNext(list); subscriber.onCompleted(); } }).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) .subscribe( new Subscriber<List<String>>() { @Override public voidonCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(List<String> list) { listener.onPhotoLoaded(list); }}); } public void getVideoAlbumList(final OnLoadAlbumListener listener) {Observable. Create (new) Observable.OnSubscribe<List<AlbumModel>>() { @Override public void call(Subscriber<? super List<AlbumModel>> subscriber) { List<AlbumModel> albums = albumController.getVideoAlbums(); subscriber.onNext(albums); subscriber.onCompleted(); } }).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) .subscribe( new Subscriber<List<AlbumModel>>() { @Override public voidonCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(List<AlbumModel> albumModels) { listener.onAlbumLoaded(albumModels); }}); } public void getAlbumList(final OnLoadAlbumListener listener) {Observable. Create (new) Observable.OnSubscribe<List<AlbumModel>>() { @Override public void call(Subscriber<? super List<AlbumModel>> subscriber) { List<AlbumModel> albums = albumController.getAlbums(); subscriber.onNext(albums); subscriber.onCompleted(); } }).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) .subscribe( new Subscriber<List<AlbumModel>>() { @Override public voidonCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(List<AlbumModel> albumModels) { listener.onAlbumLoaded(albumModels); }}); } public void getAlbumVideoList(final OnLoadPhotoListener Listener) {observable. create(new)} public void getAlbumVideoList(final OnLoadPhotoListener listener) {Observable Observable.OnSubscribe<List<DisplayInfoBean>>() { @Override public void call(Subscriber<? super List<DisplayInfoBean>> subscriber) { List<DisplayInfoBean> videos = albumController.getVideos(); subscriber.onNext(videos); subscriber.onCompleted(); } }).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) .subscribe( new Subscriber<List<DisplayInfoBean>>() { @Override public voidonCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(List<DisplayInfoBean> displayInfoBeen) {
                        listener.onVideoLoaded(displayInfoBeen);
                    }
                });
    }

    /**
     * 获取单个相册下的所有照片信息
     */
    public void getAlbumPhotoList(final String name, final OnLoadPhotoListener listener) {
        Observable.create(new Observable.OnSubscribe<List<String>>() {
            @Override
            public void call(Subscriber<? super List<String>> subscriber) {
                List<String> photos = albumController.getAlbumPic(name);
                subscriber.onNext(photos);
                subscriber.onCompleted();
            }
        }).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())
        .subscribe(
                new Subscriber<List<String>>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("= = = = = =",e.toString()); } @Override public void onNext(List<String> albumModels) { listener.onPhotoLoaded(albumModels); }}); } /** * Public interface OnLoadPhotoListener {void onPhotoLoaded(List<String> photos); / / Public interface OnLoadPhotoListener {void onPhotoLoaded(List<String> photos); void onVideoLoaded(List<DisplayInfoBean> videos); } /** * Public interface OnLoadAlbumListener {void onAlbumLoaded(List<AlbumModel> Albums); }}Copy the code

3. The selection part of the picture

In front of the album loading superfluity is no longer described, above from the use of the album loading tool, get the data, notice Recycleview (Gridview) refresh show, relatively simple no longer say too much, If the function 12345 is selected, it will change to 12 (3> empty) (4>3) (5>4). If the function 12345 is selected, it will change to 12 (3> empty) (4>3) (5>4). And will cause the screen to refresh the white screen flashing. So Diffutil is now the optimal solution.

My thoughts on some of the problems and the solutions I can come up with to my current limitations are all in the notes, but there are always omissions and better solutions.

public class PhotoPickActivity extends AppCompatActivity implements PhotoSelectorHelper.OnLoadAlbumListener,
        PhotoSelectorHelper.OnLoadPhotoListener, PopupWindow.OnDismissListener {
    private PhotoSelectorHelper mHelper;
    private RecyclerView mRecycleView;
    private PhotoVideoAdapter photoVideoAdapter;
    private TextView mCountText;
    public static final String MAX_PICK_COUNT = "max_pick_count";
    public static final String IS_SHOW_CAMERA = "isShowCamera";
    public static final String SELECT_PHOTO_LIST = "select_photo_list"; private static final int TO_PICK_ALBUM = 1; private static final int TO_PRIVIEW_PHOTO = 2; private static final int TO_TAKE_PHOTO = 3; private boolean isShowCamera; private int maxPickCount; private String mLastAlbumName; // Status bar private RelativeLayout headView; private ImageView down; private TextView album; private TextView titleText; // Albums select private PopupWindow PopupWindow; private AlbumListAdapter albumListAdapter; private TextView mCountText0; private ArrayList<String> name; private int mShowPicCount = 0; private ArrayList<String> mPicList; private ArrayList<DisplayInfoBean> videoList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(R.layout.activity_photo_pick); mPicList = new ArrayList<>(); videoList = new ArrayList<>(); MShowPicCount = getIntent().getinTextra ()"picCount", 9); /** * Select two values: 1 PIC click photo to enter 2 video click video to enter */ isShowCamera = getIntent().getBooleanExtra("isShowCamera".false);

        if (mShowPicCount == 0) {
            maxPickCount = 9;
        } else{ maxPickCount = mShowPicCount; } name = new ArrayList<>(); mLastAlbumName = AlbumHelpler.ALBUM_NAME; mCountText = (TextView) this.findViewById(R.id.tv_to_confirm); mCountText0 = (TextView) this.findViewById(R.id.tv_to_confirm0); mCountText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { selectDone(); }}); //recycler mRecycleView = (RecyclerView) this.findViewById(R.id.mp_galley_gridView); GridLayoutManager mManagerDrawable = new GridLayoutManager(this, 3); mRecycleView.setLayoutManager(mManagerDrawable); mRecycleView.setAdapter(photoVideoAdapter = new PhotoVideoAdapter(this, isShowCamera, maxPickCount)); // Initialize the title bar. Headview = (RelativeLayout) findViewById(R.id.hoto_pick); album = (TextView) findViewById(R.id.pic_head_view_commit); down = (ImageView) findViewById(R.id.pic_head_view_down); album.setText(getString(R.string.photo_pick_album)); titleText = (TextView) findViewById(R.id.pic_head_view_title); titleText.setText(R.string.photo_pick_near); ImageView backImg = (ImageView) findViewById(R.id.pic_head_view_back); TextView backText = (TextView) findViewById(R.id.pic_head_view_back_t); backImg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                setResult(RESULT_OK, intent); finish(); }}); backText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                setResult(RESULT_OK, intent); finish(); }}); ArrayList<String> list = getIntent().getStringArrayListExtra(SELECT_PHOTO_LIST);if (list == null) {
            list = new ArrayList<>();
        }

        if (list != null) {
            photoVideoAdapter.setmSelectedImage(list);
        }
        //视频还是图片的显示逻辑
        mHelper = new PhotoSelectorHelper(this);
        mHelper.getAllPics(this);
        //相册选择
        album.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showPop(); }});if (maxPickCount >= 1) {
            mCountText.setVisibility(View.VISIBLE);
            mCountText0.setVisibility(View.VISIBLE);
        } else{ mCountText.setVisibility(View.GONE); mCountText0.setVisibility(View.GONE); } photoVideoAdapter.setOnDisplayImageAdapter(new DisplayImageViewAdapter<String>() { @Override public void OnItemClick (Context Context, int index, String path) {// Check whether the address is emptyif(textutils.isempty (path)) {// Enter from post video // Jump to camera if first, and add photo if notif (Build.BRAND.equals("samsung"ACTION_IMAGE_CAPTURE = new Intent(mediastore.action_image_capture); MyApp.setPath(Environment.getExternalStorageDirectory() +"/greatchef/"
                                + RandomString.randomString(8) + ".jpg");
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(MyApp.getPath())));
                        startActivityForResult(intent, TO_TAKE_PHOTO);
                    } else {
                        Intent in = new Intent(PhotoPickActivity.this, YcCameraActivity.class);
                        startActivityForResult(in, TO_TAKE_PHOTO); }}else {
                    if (path.endsWith(".mp4")) {/ / video = = because only take out the mp4 format video / / Intent Intent = new Intent (PhotoPickActivity. This, UploadPreVideoActivity. Class); Intent intent = new Intent(PhotoPickActivity.this, YcCameraActivity.class); intent.putExtra("isShowDelect".false);
                        intent.putExtra("foodvideo", path);
                        intent.putExtra("islocal".true);
                        intent.putExtra("imgpass"."");
                        startActivity(intent);
                    } else {
                        Intent intent = new Intent(PhotoPickActivity.this, PhotoPreviewActivity.class);
                        Log.d("= = = = = = = = >", index + "");
                        intent.putExtra(PhotoPreviewActivity.PHOTO_PATH_IN_ALBUM, index);
                        intent.putExtra("isShowCamera", isShowCamera);
                        intent.putExtra(MAX_PICK_COUNT, maxPickCount);
                        intent.putExtra("album_name", mLastAlbumName);
                        intent.putStringArrayListExtra("select", (ArrayList<String>) photoVideoAdapter.getmSelectedImage()); startActivityForResult(intent, TO_PRIVIEW_PHOTO); } } } @Override public void onDisplayImage(Context context, ImageView imageView, String s) { } @Override public void onItemImageClick(Context context, int index, List<String> list) { } @Override public void onImageCheckL(String path, Boolean isChecked) {/ / / need to deal with. / / photoVideoAdapter notifyDataSetChanged (); updateCountView(); }}); updateCountView(); } /** * Displays a list of albums */ private voidshowPop() {// Display logic mhelper.getalbumList (this); down.setBackgroundResource(R.mipmap.photo_havepic_down); ListView mListView; View view = LayoutInflater.from(this).inflate(R.layout.activity_album_pick, null); mListView = (ListView) view.findViewById(R.id.lv_show_album); view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(popupWindow ! = null && popupWindow.isShowing()) { popupWindow.dismiss(); }}}); albumListAdapter = new AlbumListAdapter(this, name); mListView.setAdapter(albumListAdapter); mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<? > parent, View View, int position, long id) {mLastAlbumName = albumListAdapter.getitem (position).getName();if (name.size() > 0) {
                    name.set(0, mLastAlbumName);
                } else {
                    name.add(mLastAlbumName);
                }
                titleText.setText(mLastAlbumName);
                if (AlbumHelpler.ALBUM_NAME.equals(mLastAlbumName)) {
                    mHelper.getAllPics(PhotoPickActivity.this);
                } else if (AlbumHelpler.VIDEO_NAME.equals(mLastAlbumName)) {
                    mHelper.getAlbumVideoList((PhotoSelectorHelper.OnLoadPhotoListener) PhotoPickActivity.this);
                } else {
                    mHelper.getAlbumPhotoList(mLastAlbumName, (PhotoSelectorHelper.OnLoadPhotoListener) PhotoPickActivity.this);
                }
                if(popupWindow ! = null) { popupWindow.dismiss(); }}});if (popupWindow == null) {
            popupWindow = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT, true);
            popupWindow.setBackgroundDrawable(new ColorDrawable(0xb0000000));
            popupWindow.setOutsideTouchable(true);
            popupWindow.setOnDismissListener(this);
        }
        if(! popupWindow.isShowing()) { popupWindow.showAsDropDown(headview); }else{ popupWindow.dismiss(); @param photos */ @override public void onPhotoLoaded(List<String> photos) { Otherwise the photoVideoAdapter. NotifyDataSetChanged (photos); Mpiclist.clear (); mpiclist.clear (); mPicList.addAll(photos); photoVideoAdapter.notifyDataSetChanged(photos); } @Override public void onVideoLoaded(List<DisplayInfoBean> videos) { photoVideoAdapter.notifyVideoDtChanged(videos); Public void onAlbumLoaded(List<AlbumModel> Albums) {public void onAlbumLoaded(List<AlbumModel> Albums)if(null ! = albums && albums.size() ! = 0) { albumListAdapter.notifyDataSetChanged(albums); }else {
            albumListAdapter.notifyDataSetChanged(new ArrayList<AlbumModel>());
            Toast.makeText(this, getString(R.string.photo_empty), Toast.LENGTH_SHORT).show();
            popupWindow.dismiss();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode ! = RESULT_OK) {return;
        }
        switch (requestCode) {

            caseTO_PRIVIEW_PHOTO: updateCountView(); /// If you want to go to the next PhotoPreViewActivity to view the larger image, mhelper. getAllPics will be regenerated in this page. Take a photo by yourself, then enter the preview // results in the preview page data is relatively new, there is one more photo. "//" // "//" // "//" // "// If the number of preview pages is different, the total amount of data is returned. If the number of preview pages is different, the data on the current page is updated. However, there is still problem 1, which is caused by the inability to press the home keyboard to take several photos and then delete the same number of photos. But I'm too lazy to write. // Workaround: Update album data at onRsume. The disadvantage is that the photos may be slow when there is a large amount of data. // There is still a problem 2. In the above case, the selected photos are deleted, but the selected list is not deleted in the update. Traverses the currently selected list to see if it exists in the album list. Using popWindow, data operation in the current page, has obvious advantages, one less page, one less query, but the problem is that there will be more data problems, such as the problem of selecting operation data refresh in the preview, // Currently using method 2, So this comment is also in the onActivityResult... photoVideoAdapter.setmSelectedImage(data.getStringArrayListExtra("select")); // The selected data needs to be sent back, thensetInto the Adapter so that the Adapter can operate on the selected data.if (isShowCamera) {
                    if((mPicList.size() - 1) ! = data.getIntExtra("count", 0)) {
                        mHelper.getAllPics(this);
                    } else{ photoVideoAdapter.notifyDataSetChanged(mPicList); // photoVideoAdapter.notifyDataSetChanged(); }}else {
                    if(mPicList.size() ! = data.getIntExtra("count", 0)) {
                        mHelper.getAllPics(this);
                    } else{ photoVideoAdapter.notifyDataSetChanged(mPicList); // photoVideoAdapter.notifyDataSetChanged(); }}break;
            caseTO_TAKE_PHOTO: // Samsung phone used the system camera to take the photo, because the Angle was not controlled at that time, it was 90 degrees, and I was too lazy to change it later...if (Build.BRAND.equals("samsung")) {
                    File file = new File(MyApp.getPath());
                    PictureUtil.notifyGallery(this, MyApp.getPath());
                    photoVideoAdapter.getmSelectedImage().add(MyApp.getPath());
                    selectDone();
                } else {
                    String url = data.getStringExtra("imgp");
                    PictureUtil.notifyGallery(this, url);
                    photoVideoAdapter.getmSelectedImage().add(url);
                    selectDone();
                }
                break;

        }
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == android.R.id.home) {
            finish();
            return true;
        }
        returnsuper.onOptionsItemSelected(item); ArrayList<String> list = new ArrayList<>(); ArrayList<String> list = new ArrayList<>(); // Data saved in MyApp after last selected private voidselectDone() {
        PicCompress video;
        if (MyApp.getApp().getPiclist() == null || MyApp.getApp().getPiclist().size() == 0) {
            video = new PicCompress();
        } else {
            video = MyApp.getApp().getPiclist().get(0);
        }
        MyApp.getApp().getPiclist().clear();

        if(photoVideoAdapter.getmSelectedImage() ! = null) {for (int i = 0; i < photoVideoAdapter.getmSelectedImage().size(); i++) {
                MyApp.getApp().getPiclist().add(
                        new PicCompress(photoVideoAdapter.getmSelectedImage().get(i), "".false)); list.add(photoVideoAdapter.getmSelectedImage().get(i)); } / /if (isShowCamera) {
//                MyApp.getApp().getPiclist().add(0, video);
//            }
        }
        Intent intent = new Intent();
        intent.putStringArrayListExtra(SELECT_PHOTO_LIST, list);
        setResult(RESULT_OK, intent);
        finish();
    }

    public void selectVideo(String path) {
        Intent intent = new Intent();
        PicCompress compress = new PicCompress();
        compress.setPicadress(path);
        if(MyApp.getApp().getPiclist() ! = null && MyApp.getApp().getPiclist().size() ! = 0) { MyApp.getApp().getPiclist().remove(0); } MyApp.getApp().getPiclist().add(0, compress); intent.putExtra("videoPath", path);
        setResult(RESULT_OK, intent);
        finish();
    }

    private void updateCountView() {
        if (photoVideoAdapter.getmSelectedImage().size() == 0) {
            mCountText.setEnabled(false);
            mCountText0.setEnabled(false);

        } else {
            mCountText.setEnabled(true);
            mCountText0.setEnabled(true);

        }
        mCountText.setText(getString(R.string.head_welldone) + "(" + photoVideoAdapter.getmSelectedImage().size() + "/" + maxPickCount + ")");
    }

    @Override
    public void onDismiss() { down.setBackgroundResource(R.mipmap.photo_havepic_up); }}Copy the code

4. The Adapter of the album

The logic of this part of the involved more, less I tried my best to try to write clear my logic, but it still looks messy Main processing the selected logic in holder. SelectFlag. SetOnClickListener, I wrote about this part of code comments. The existing result is to increase the uncheck, modify only the items that need to be modified, such as increase the unmask, change the selected number. The main logic is:

  • To add a selected image, you only need to cover the gray mask of the image, and the selected number is the selected number.
  • Deselect:
  • Uncheck the last digit, just uncheck the gray mask of the image and select the number hide.
  • If the last digit is not the last digit, remove the mask + number from the current position, from the cancelled position (for example, cancel the third picture, then the 1/2 and two pictures can remain unchanged, only change the figure behind 3), the mask remains, and the number decreases by 1.
  • The operation of changing the current click picture can directly change the number + mask and other states in the click event. For other adjustments, adapter.notify is required. However, we do not want notify() to prevent flash screen, so we adopt the following method: Notify YItemChanged (position, payload)/notifyItemRangeChanged(Position, 1, payload) playLoad is not empty The method reference link using onBindViewHolder() is dropped

For those of you interested, see how Dffutils works. The bindViewholder method uses the three parameters, and you can override the method with the next three parameters to carry information in the payloads. This article also uses this part of Diffutils for a local refresh.

Therefore, you only need to add the payload parameter in the change area and change the three-parameter method. Refer to the code for details

/** * Created by Cuiliubi */ public class PhotoVideoAdapter extends RecyclerView. Adapter < PhotoVideoAdapter. MyViewHolder > {/ / the user's choice of pictures, pictures stored as the full path of the public ArrayList < String > mSelectedImage; Private ArrayList<Integer> mSelectedImagePosition; // Record the position of the selected image in the entire mPiclist. protected ArrayList<Photobean> mPicList; // List protected ArrayList<DisplayInfoBean> mVideoList; private int maxCount; private LayoutInflater mInflater; private DisplayImageViewAdapter<String> mDisplayAdapter; private boolean isShowCamera; private PhotoVideoAdapter adapter; public List<String>getmSelectedImage() {
        returnmSelectedImage; } /** * select list, * @param mSelectedImage */ public void setmSelectedImage(ArrayList<String> select) { mSelectedImage.clear(); mSelectedImage.addAll(select);if(mPicList ! = null && mPicList.size() > 0) { mSelectedImagePosition.clear();for (int i = 0; i < mPicList.size(); i++) {
                if (select.contains(mPicList.get(i).getPath())) {
                    mPicList.get(i).setSelect(select.indexOf(mPicList.get(i).getPath()));
                    mSelectedImagePosition.add(i);
                }

                if(select. The size () = = mSelectedImagePosition. The size ()) {/ / when have found all the selected photos will be ready to jump out of the loop (the method)return;
                }
            }
        }

    }

    public PhotoVideoAdapter(Context mContext, boolean isShowCamera, int maxCount) {
        this.mContext = mContext;
        this.maxCount = maxCount;
        this.isShowCamera = isShowCamera;
        mInflater = LayoutInflater.from(mContext);
        mSelectedImage = new ArrayList<>();
        mSelectedImagePosition = new ArrayList<>();
        mPicList = new ArrayList<>();
        if (isShowCamera) {
            Photobean bean = new Photobean(0, "");
            mPicList.add(0, bean);
        }
        adapter = this;
    }

    public PhotoVideoAdapter(Context mContext, boolean isShowCamera, int maxCount, ArrayList<String> mSelectedImage, ArrayList<Integer> mSelectedImagePosition,ArrayList<Photobean> mPicList) {
        this.mContext = mContext;
        this.maxCount = maxCount;
        this.isShowCamera = isShowCamera;
        mInflater = LayoutInflater.from(mContext);
        this.mSelectedImage =mSelectedImage;
        this.mSelectedImagePosition = mSelectedImagePosition;
        this.mPicList=mPicList;
        mPicList = new ArrayList<>();
        if (isShowCamera) {
            Photobean bean = new Photobean(0, "");
            mPicList.add(0, bean);
        }
        setmSelectedImage(mSelectedImage);
        adapter = this;
    }


    public void setOnDisplayImageAdapter(DisplayImageViewAdapter<String> adapter) {
        this.mDisplayAdapter = adapter;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        PhotoVideoAdapter.MyViewHolder holder;
        if (viewType == 1) {
            holder = new PhotoVideoAdapter.MyViewHolder(mInflater.inflate(R.layout.grid_photo_item, parent, false));
        } else {
            holder = new PhotoVideoAdapter.MyViewHolder(mInflater.inflate(R.layout.grid_camera_item, parent, false));
        }
        return holder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        if (mDisplayAdapter == null) {
            return;
        }
        if (isShowCamera == true) {
            if (position == 0) {

                holder.textFirst.setText(mContext.getString(R.string.photo_take));
                holder.imgFirst.setImageResource(R.mipmap.photo_icon_takephoto);

                holder.camera.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (mSelectedImage.size() < maxCount) {
                            mDisplayAdapter.onItemClick(mContext, 0, "");
                        } else {
                            Toast.makeText(mContext.getApplicationContext(),
                                    "No more than" + maxCount + "A picture", Toast.LENGTH_SHORT).show(); }}}); }else {
                bindItemView(holder, position); }}else {
            bindItemView(holder, position); } } @Override public void onBindViewHolder(final MyViewHolder holder, final int position, List<Object> payloads) {// The whole data can be added or deleted using diffUtil, otherwise, for example, the state can be selected without using diffutil. // The problem is that you have to compare data manually, so when you uncheck it, you have to adjust up to 9 (maxCount) loads;if (payloads.isEmpty()) {
            onBindViewHolder(holder, position);
        } else {
            Bundle payload = (Bundle) payloads.get(0);
            Photobean bean = mPicList.get(position);
            for (String key : payload.keySet()) {
                switch (key) {
                    case "SELECT"// You can use the data payload, but you can also use dataif(bean. GetSelect () = = 0) {/ / not selected holder. SelectFlag. SetSelected (false);
                            holder.img.setColorFilter(null);
                            holder.text.setVisibility(View.INVISIBLE);
                        } else{/ / / / has been selected the selected photos of display logic holder. SelectFlag. SetSelected (true);
                            holder.img.setColorFilter(0x80000000);
                            holder.text.setVisibility(View.VISIBLE);
                            holder.text.setText(mPicList.get(position).getSelect() + "");
                        }
                        Glide.with(mContext).load(mPicList.get(position).getPath()).into(holder.img);
                        break;
                    case "PATH"// Small dot click logicbreak;


//                    case "CANCLE": // unselected //break;

                    case "CHANGE": / / change data holder. SelectFlag. SetSelected (true);
                        holder.img.setColorFilter(0x80000000);
                        holder.text.setVisibility(View.VISIBLE);
                        holder.text.setText(mPicList.get(position).getSelect() + "");
                        break;
                    default:
                        break;
                }


            }

        }
    }

    public void bindItemView(final MyViewHolder holder, final int position) {// Photo hold.video_time.setvisibility (view.gone); holder.shader_text.setVisibility(View.GONE); // The logic of the dots on the pictureif (maxCount >= 1) {
            holder.selectFlag.setVisibility(View.VISIBLE);
        } else{ holder.selectFlag.setVisibility(View.GONE); Glide. With (mContext).load(mpicList.get (position).getPath()).into(holder.img); // Display logic for selected photosif (mPicList.get(position).getSelect() > 0) {
            holder.selectFlag.setSelected(true);
            holder.img.setColorFilter(0x80000000);
            holder.text.setVisibility(View.VISIBLE);
            holder.text.setText(mPicList.get(position).getSelect() + "");
        } else {
            holder.selectFlag.setSelected(false); holder.img.setColorFilter(null); holder.text.setVisibility(View.INVISIBLE); } / / dots. Click on the logical holder selectFlag. SetOnClickListener (new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean isChecked = mPicList.get(position).getSelect() > 0;
                if (isChecked) {
                    holder.selectFlag.setSelected(false); holder.img.setColorFilter(null); holder.text.setVisibility(View.INVISIBLE); / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / * * * The middle part of the three lines // can be done completely without operation, Directly in mDisplayAdapter. OnImageCheckL (callback for adapter. Notify can realize operation * * * but in order to avoid increasing/deselect brings recycleview refresh all data caused by flashing, adopting partial refresh. Think of two ways for a moment. It has not yet been considered which method saves more performance * of course, logically speaking, there is no doubt that method 1 is simpler and more convenient without the onBindViewHolder operation. * there are two ways to do this: 1. Walk through the mPiclist, create a new newList, and add the updated data to the newList. Then use the diff method below to compare the newList. Use notifyItemRangeChanged; This method requires onBindViewHolder to take care of the operation. The following way: * 2.1, improve the way 2, still manual refresh, in setmSelectImg, get these selected in the overall album list position, adjust, the same use * * * * now using the way 2.1, although do not know how much performance can save... * general idea has joined the comments in the following, the overall operations in accordance with the following ideas for * 1 if the current is a selected cancel finally, directly cancel without doing any operation * 2 if it is not the last selected to cancel, so cancel the selected top need not operation, only need to cancel the position to cancel the selected operation, * */ int index = mselecteDimage.indexof (mpicList.get (position).getPath()); Mpiclist.get (position).setSelect(0); // All positions need to be adjusted. For example, if the first one is unselected, all subsequent ones need to be reset. // If the last one is unselected, the other positions need to be changedif(index == mselecteDimage.size () -1) {// last position // last position, You just need to refresh the current itemview mPicList. Get (mSelectedImagePosition. Get (index). SetSelect (0); mSelectedImage.remove(mPicList.get(position).getPath()); mSelectedImagePosition.remove(new Integer(position)); }else{// deselect the non-last bit of the index, consider, do not change the data display before index, only after index, so start from index+1 to loop through the selected mSelectImagefor(int i = index + 1; i < mSelectedImage.size(); I++) {// the index position is the unselected position, so change the selected data from the next position, The index in the future numerical reduce 1 mPicList. Select the get (mSelectedImagePosition. Get (I)). SetSelect (I); // Set ho Bundle payload = new Bundle(); payload.putInt("CHANGE", mSelectedImagePosition.get(i)); / / notice next position change data adapter. NotifyItemChanged (mSelectedImagePosition. Get (I), content; } // Unselect the selected image position // In mPicList, delete the point dataif(index >= 0) { mPicList.get(mSelectedImagePosition.get(index)).setSelect(0); } mSelectedImage.remove(mPicList.get(position).getPath()); mSelectedImagePosition.remove(new Integer(position)); } / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /}else {
                    if (mSelectedImage.size() >= maxCount) {
                        Toast.makeText(mContext.getApplicationContext(),
                                "No more than" + maxCount + "A picture", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    mSelectedImage.add(mPicList.get(position).getPath());
                    mSelectedImagePosition.add(position);
                    mPicList.get(position).setSelect(mSelectedImage.size());
                    holder.text.setVisibility(View.VISIBLE);
                    holder.text.setText(mPicList.get(position).getSelect() + "");
                    holder.selectFlag.setSelected(true); holder.img.setColorFilter(0x80000000); } mDisplayAdapter.onImageCheckL(mPicList.get(position).getPath(), ! isChecked); }}); / / add a click event holder. Img. SetOnClickListener (new View.OnClickListener() { @Override public void onClick(View v) { mDisplayAdapter.onItemClick(mContext, mPicList.indexOf(mPicList.get(position)), mPicList.get(position).getPath()); }}); } @Override public int getItemViewType(int position) {if (isShowCamera && position == 0) {
            return 0;
        } else {
            return 1;
        }
    }

    @Override
    public int getItemCount() {
        returnmPicList == null ? 0 : mPicList.size(); } class MyViewHolder extends RecyclerView.ViewHolder { TextView text; TextView textFirst; TextView video_time; ImageView img; ImageView shader_text; ImageView imgFirst; ImageView selectFlag; SquareRelativeLayout camera; // In fact, the two layouts share the same holder... Public MyViewHolder(View itemView) {super(itemView); text = (TextView) itemView.findViewById(R.id.text); video_time = (TextView) itemView.findViewById(R.id.video_time); img = (ImageView) itemView.findViewById(R.id.ic_image_pick); shader_text = (ImageView) itemView.findViewById(R.id.shader_text); selectFlag = (ImageView) itemView.findViewById(R.id.ic_check_box); ImgFirst = (ImageView) ItemView.findViewById (r.i.C.amera_pick); camera = (SquareRelativeLayout) itemView.findViewById(R.id.camera_id); textFirst = (TextView) itemView.findViewById(R.id.camera_text); }} /** * update data */ public void notifyDataSetChanged(List<String> mList) {ArrayList<Photobean> List = new ArrayList();if (mList == null) {
            mList = new ArrayList<>();
        }

        if (isShowCamera) {
            if(mList.size()>0&&! TextUtils.isEmpty(mList.get(0))){ mList.add(0,""); }}for(int i = 0; i < mList.size(); I++) {mSelectedImagePosition Photobean = new Photobean(0, 0);"");
            if (mSelectedImage.contains(mList.get(i))) {
                bean.setSelect(mSelectedImage.indexOf(mList.get(i)) + 1);
                mSelectedImagePosition.add(i);
                bean.setPath(mList.get(i));
            } else{ bean.setSelect(0); bean.setPath(mList.get(i)); } list.add(bean); } diff(list, mPicList, this); Clear (); // mpiclist.clear (); // mPicList.addAll(list); // adapter.notifyDataSetChanged(); } public void notifyVideoDtChanged(List<DisplayInfoBean> mList) {this.mvideolist.clear ();} public void notifyVideoDtChanged(List<DisplayInfoBean> mList) {this.mvideolist.if (mList == null) {
            mList = new ArrayList<>();
        }
        if (isShowCamera) {
            mList.add(0, new DisplayInfoBean(""."")); } this.mVideoList.addAll(mList); this.notifyDataSetChanged(); } /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * @param newList @param oldList @param photoVideoAdapter private void diff(final ArrayList<Photobean> newList, final ArrayList<Photobean> oldList, Final PhotoVideoAdapter PhotoVideoAdapter) {// put it into the worker thread to do the operation rx.Observable. Create (new) rx.Observable.OnSubscribe<DiffUtil.DiffResult>() { @Override public void call(Subscriber<? super DiffUtil.DiffResult> subscriber) { DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffPhotoPickCallback(newList, oldList, 0)); subscriber.onNext(diffResult); subscriber.onCompleted(); } }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<DiffUtil.DiffResult>()  { @Override public void call(DiffUtil.DiffResult diffResult) { diffResult.dispatchUpdatesTo(photoVideoAdapter); mPicList.clear(); mPicList.addAll(newList); }}); }}Copy the code

5. Partial refresh of Recycleview

In fact, this part has been out for a long time, although there are two articles, but I have not studied the code very seriously, taking the advantage of this summary of this part of the content is also to give myself an explanation… This part has a very detailed reference in other people’s articles, I will not repeat the reference article

/** * Created by Cuiliubi on 18/1/12 Thu Recycleview flash public class DiffPhotoPickCallback extends DiffUtil.Callback {protected ArrayList<Photobean> newPic, oldPic; protected List<DisplayInfoBean> newVideo, oldVideo; private int isType = 0; // 0 image, 1 video, there is no video for now, it seems that the video is not needed, because after clicking on it, it will be returned. @override public Object getChangePayload(int oldItemPosition, int newItemPosition) { Himself in learning while doing, reference from the / / http://blog.csdn.net/zxt0601/article/details/52562770 Photobean oldBean = oldPic. Get (oldItemPosition); Photobean newBean = newPic.get(newItemPosition); // Bundle payload = new Bundle();if(oldBean.getSelect() ! = newBean.getSelect()) { payload.putInt("SELECT", newBean.getSelect());
        }
        if(! oldBean.getPath().equals(newBean.getPath())) { payload.putString("PATH", newBean.getPath());
        }

        if(payload-size () == 0)// Empty if there is no changereturn null;
        returnpayload; // } public DiffPhotoPickCallback(ArrayList<Photobean> newPic, ArrayList<Photobean> oldPic, int isType) { this.newPic = newPic; this.oldPic = oldPic; this.isType = isType; } public DiffPhotoPickCallback(List<DisplayInfoBean> newVideo, List<DisplayInfoBean> oldVideo, int isType) { this.newVideo = newVideo; this.oldVideo = oldVideo; this.isType = isType; } @Override public intgetOldListSize() {
        if (isType == 0) returnoldPic ! = null ? oldPic.size() : 0;else if (isType == 1) returnoldVideo ! = null ? oldVideo.size() : 0;return 0;
    }

    @Override
    public int getNewListSize() {
        if (isType == 0) returnnewPic ! = null ? newPic.size() : 0;else if (isType == 1) returnnewVideo ! = null ? newVideo.size() : 0;return0; } @override public Boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {if(isType == 0)// If the address is the same, it can be considered the same itemreturn newPic.get(newItemPosition).getPath().equals(oldPic.get(oldItemPosition).getPath());
        else returnnewVideo.get(newItemPosition) == newVideo.get(oldItemPosition); Override public Boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {Override public Boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {if (isType == 0)
            return newPic.get(newItemPosition).getSelect() == oldPic.get(oldItemPosition).getSelect() && newPic.get(newItemPosition).getPath().equals(oldPic.get(oldItemPosition).getPath());
        else
            returnnewVideo.get(newItemPosition).getAddTime().equals(oldVideo.get(oldItemPosition).getAddTime()) && oldVideo.get(newItemPosition).getPath().equals(newVideo.get(oldItemPosition).getPath()); }}Copy the code