Krish maurya
Krish maurya

Reputation: 11

How to load large number of images in recyclerview?

I have an activity where user is allowed to select around 500 images and then moves to next activity where those images will populated in a RecyclerView, how should i make it all work, for smooth user experience and better performance.

Currently i'm passing the images as bitmaps using intents.

I'm using the photopicker library for photo selection, here user is allowed to select multiple images and the filepath of all the selected images gets stored in a string Arraylist, which gets returned in the onActivityResult of the activity, i'm storing the result in mUserSelectedPhotos named string arraylist below is some code for reference.

PhotoPickingActivity.java

mPickImagesButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            PhotoPicker.builder()
                    .setPhotoCount(200)
                    .setShowCamera(true)
                    .setShowGif(true)
                    .setPreviewEnabled(true)
                    .start(ChoosePhotoBookImagesActivity.this, PhotoPicker.REQUEST_CODE);
        }
    });


   @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (resultCode == RESULT_OK && requestCode == PhotoPicker.REQUEST_CODE) {
        if (data != null) {
            mUserSelectedPhotos =
                    data.getStringArrayListExtra(PhotoPicker.KEY_SELECTED_PHOTOS);
        }
    }
}

on click of the next button the the user selected images string arraylist gets passed to the next activity through intent.

PhotoPickingActivity.java

 mNextButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(PhotoPickingActivity.this, PhotoBookListViewActivity.class);
            intent.putStringArrayListExtra("USER_SELECTED_IMAGES", mUserSelectedPhotos);
            startActivity(intent);
        }
    });

In the next activity which contains the recyclerview, i'm receiving the sent intent within this activity and the received data in the intent is the arraylist of string which contains the filepaths of the images which user selected in the previous activity.

PhotoBookListViewActivity.java

Intent intent = getIntent();
mReceivedImageList = intent.getStringArrayListExtra("USER_SELECTED_IMAGES");

i'm reading through the mReceivedImageList and converting the filepaths to bitmaps and storing it in the new bitmap arraylist.

PhotoBookListViewActivity.java

 final ArrayList<PhotoBookViewModel> bitmapImages = new ArrayList<PhotoBookViewModel>();

    for (int i = 0; i < mImageList.size(); i++) {
        mPhotoUrl = mImageList.get(i).toString();
        Bitmap myBitmap = BitmapFactory.decodeFile(mPhotoUrl);
        bitmapImages.add(new PhotoBookViewModel(myBitmap));
    }

passing the bitmapImages arraylist which is the list of bitmap images to the adapter.

PhotoBookListViewActivity.java

mPhotoBookViewAdapter = new PhotoBookViewAdapter(PhotoBookListViewActivity.this, bitmapImages);

mPhotoBookViewRecyclerView.setAdapter(mPhotoBookViewAdapter);

mPhotoBookViewRecyclerView.setLayoutManager(new LinearLayoutManager(PhotoBookListViewActivity.this, LinearLayoutManager.VERTICAL, false));

PhotoBookViewModel.java

import android.graphics.Bitmap;

public class PhotoBookViewModel {

private Bitmap mImageRes;

public PhotoBookViewModel(Bitmap imageRes) {
    this.mImageRes = imageRes;
}

public Bitmap getImageRes() {
    return mImageRes;
}
}

PhotoBookViewAdapter.java

public class PhotoBookViewAdapter extends RecyclerView.Adapter<PhotoBookViewAdapter.PhotoViewHolder> {

private ArrayList<PhotoBookViewModel> mData;
private LayoutInflater mLayoutInflater;
private View mImageItemView;
private ArrayList<String> mSelectedPhotos;
private Bitmap mBitmap;
private Context mContext;

public class PhotoViewHolder extends RecyclerView.ViewHolder {

    private ImageView mImageView;

    public PhotoViewHolder(@NonNull View itemView) {
        super(itemView);
        mImageView = itemView.findViewById(R.id.imageview);
    }

    public void setData(PhotoBookViewModel currentObj) {
        this.mImageView.setImageBitmap(currentObj.getImageRes());
    }
}

public PhotoBookViewAdapter(Context context, ArrayList<String> selectedPhotos) {
    this.mContext = context;
    this.mSelectedPhotos = selectedPhotos;
    mBitmap = BitmapFactory.decodeFile (mSelectedPhotos.get(0).toString());
}

public PhotoBookViewAdapter(Context context, ArrayList<PhotoBookViewModel> mData) {
    this.mData = mData;
    mLayoutInflater = LayoutInflater.from(context);
}

@NonNull
@Override
public PhotoViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    mImageItemView = LayoutInflater.from(viewGroup.getContext())
            .inflate(R.layout.photo_book_view_image_item, viewGroup, false);
    PhotoViewHolder photoViewHolder = new PhotoViewHolder(mImageItemView);
    mContext = viewGroup.getContext();
    return photoViewHolder;
}

@Override
public void onBindViewHolder(@NonNull PhotoViewHolder photoViewHolder, int position) {
    PhotoBookViewModel currentObj = mData.get(position);
    photoViewHolder.setData(currentObj);;
}

@Override
public int getItemCount() {
    return mData.size();
}

}

Upvotes: 1

Views: 1097

Answers (1)

Slobodan Antonijević
Slobodan Antonijević

Reputation: 2643

I'd use Glide for this purpose, it loads images async, and loads the bitmap in the background. There absolutely no need for you to load a bunch of Bitmap-s at all. You just need a list of Uri-s or a list of their String representations

For each image in your list get a Uri String (path to file you already collect in String representation) and then just do something like this

If you stored Uri-s, first get the String value of the Uri for the image (if you already stored String representations od Uri-s skip the next line)

String imageUriString = imageUri.getPath();

Then use Glide to elegantly load the image to your container

Glide.with(myContext)
    .load(new File(imageUriString))
    .into(R.id.image_container);

Glide is a rather powerful tool, widely used, even recommended by Google, so there's no need to reinvent the wheel :)

Cheers

Upvotes: 3

Related Questions