图库视频缩略图在 android recyclerview 中加载速度极慢

Gallery video thumbnails load extremely slow in android recyclerview

我试图在 recyclerview 中显示本地图库中的所有用户视频缩略图,但它加载缩略图非常慢(加载所有视频缩略图需要将近 10 秒)。代码如下:

VideoGalleryAdapter.java:

    public class VideoGalleryAdapter extends RecyclerView.Adapter<VideoGalleryAdapter.viewHolder> {

    public OnItemClickListener onItemClickListener;
    Context context;
    ArrayList<VideoGalleryModel> videoArrayList;

    public VideoGalleryAdapter(Context context, ArrayList<VideoGalleryModel> videoArrayList) {
        this.context = context;
        this.videoArrayList = videoArrayList;
    }

    @Override
    public VideoGalleryAdapter.viewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(context).inflate(R.layout.video_list, viewGroup, false);
        return new viewHolder(view);
    }

    @Override
    public void onBindViewHolder(final VideoGalleryAdapter.viewHolder holder, final int i) {
        holder.videoDuration.setText(videoArrayList.get(i).getVideoDuration());
        Glide.with(context).asBitmap().load(videoArrayList.get(i).getVideoThumb()).into(holder.videoThumb);
    }

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

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    public interface OnItemClickListener {
        void onItemClick(int pos, View v);
    }

    public class viewHolder extends RecyclerView.ViewHolder {
        TextView videoDuration;
        ImageView videoThumb;

        public viewHolder(@NonNull View itemView) {
            super(itemView);
            videoDuration = itemView.findViewById(R.id.videoDuration);
            videoThumb = itemView.findViewById(R.id.videoThumb);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onItemClickListener.onItemClick(getAdapterPosition(), v);
                }
            });
        }
    }
}

AddVideoActivity.java:

    public class AddVideoActivity extends AppCompatActivity {

    public static final int PERMISSION_READ = 0;
    public static ArrayList<VideoGalleryModel> videoArrayList;
    RecyclerView videoGalleryRV;
    ImageButton backBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_video);

        backBtn = findViewById(R.id.backBtn);

        backBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

        if (checkPermission()) {
            videoList();
        }
    }

    public void videoList() {
        videoGalleryRV = findViewById(R.id.videoGalleryRV);
        videoGalleryRV.setLayoutManager(new GridLayoutManager(this, 3));
        videoGalleryRV.setItemAnimator(new DefaultItemAnimator());
        videoArrayList = new ArrayList<>();
        getVideos();
    }

    //get video files from storage
    public void getVideos() {
        ContentResolver contentResolver = getContentResolver();
        Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;

        Cursor cursor = contentResolver.query(uri, null, null, null, null);

        //looping through all rows and adding to list
        if (cursor != null && cursor.moveToFirst()) {
            do {
                String duration = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DURATION));
                String data = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
                Bitmap bmp = ThumbnailUtils.createVideoThumbnail(data, MediaStore.Video.Thumbnails.MINI_KIND);

                VideoGalleryModel videoModel = new VideoGalleryModel();

                videoModel.setVideoThumb(bmp);
                videoModel.setVideoUri(Uri.parse(data));
                videoModel.setVideoDuration(timeConversion(Long.parseLong(duration)));
                videoArrayList.add(videoModel);
            } while (cursor.moveToNext());
        }

        VideoGalleryAdapter videoGalleryAdapter = new VideoGalleryAdapter(this, videoArrayList);
        videoGalleryRV.setAdapter(videoGalleryAdapter);

        videoGalleryAdapter.setOnItemClickListener(new VideoGalleryAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(int pos, View v) {
                Toast.makeText(AddVideoActivity.this, "Video Clicked", Toast.LENGTH_SHORT).show();
            }
        });
    }

    //time conversion
    public String timeConversion(long value) {
        String videoTime;
        int dur = (int) value;
        int hrs = (dur / 3600000);
        int mns = (dur / 60000) % 60000;
        int scs = dur % 60000 / 1000;

        if (hrs > 0) {
            videoTime = String.format("%02d:%02d:%02d", hrs, mns, scs);
        } else {
            videoTime = String.format("%02d:%02d", mns, scs);
        }
        return videoTime;
    }

    //runtime storage permission
    public boolean checkPermission() {
        int READ_EXTERNAL_PERMISSION = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
        if ((READ_EXTERNAL_PERMISSION != PackageManager.PERMISSION_GRANTED)) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_READ);
            return false;
        }
        return true;
    }

    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_READ) {
            if (grantResults.length > 0 && permissions[0].equals(Manifest.permission.READ_EXTERNAL_STORAGE)) {
                if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
                    Toast.makeText(getApplicationContext(), "Please allow storage permission", Toast.LENGTH_LONG).show();
                } else {
                    videoList();
                }
            }
        }
    }
}

activity_add_video.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".AddVideoActivity">

    <RelativeLayout
        android:id="@+id/headerContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="15dp">

        <ImageButton
            android:id="@+id/backBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent"
            android:padding="10dp"
            android:src="@drawable/ic_arrow_back"
            android:tint="@android:color/black" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginStart="25dp"
            android:layout_toEndOf="@id/backBtn"
            android:fontFamily="@font/gilroymedium"
            android:text="Choose video"
            android:textColor="@android:color/black"
            android:textSize="22sp" />

    </RelativeLayout>

    <View
        android:id="@+id/headerDivider"
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:layout_below="@id/headerContainer"
        android:background="@android:color/darker_gray" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/videoGalleryRV"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/headerDivider"
        android:overScrollMode="never" />

</RelativeLayout>

VideoGalleryModel.java:

public class VideoGalleryModel {

    Bitmap videoThumb;
    String videoDuration;
    Uri videoUri;

    public Bitmap getVideoThumb() {
        return videoThumb;
    }

    public void setVideoThumb(Bitmap videoThumb) {
        this.videoThumb = videoThumb;
    }

    public String getVideoDuration() {
        return videoDuration;
    }

    public void setVideoDuration(String videoDuration) {
        this.videoDuration = videoDuration;
    }

    public Uri getVideoUri() {
        return videoUri;
    }

    public void setVideoUri(Uri videoUri) {
        this.videoUri = videoUri;
    }
}

video_list.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:id="@+id/mainVideoContainer"
        android:layout_width="125dp"
        android:layout_height="125dp"
        android:layout_marginBottom="5dp"
        android:background="@color/colorBlackTransparent">

        <ImageView
            android:id="@+id/videoThumb"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/ic_launcher_background"
            android:scaleType="centerCrop"/>

        <TextView
            android:id="@+id/videoDuration"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="00:06"
            android:padding="5dp"
            android:layout_marginEnd="10dp"
            android:layout_alignParentEnd="true"
            android:layout_alignParentBottom="true"
            android:fontFamily="@font/gilroysemibold"
            android:textColor="@android:color/white"/>

    </RelativeLayout>

</RelativeLayout>

我只想知道在 recyclerview 中显示视频缩略图的正确方法以及如何更快地加载它。如果您还有其他问题,请问我,我很乐意回答。任何帮助将不胜感激

因为创建视频缩略图是一项繁重的操作。所以这需要时间。 尝试评论这些行

//Bitmap bmp = ThumbnailUtils.createVideoThumbnail(data, MediaStore.Video.Thumbnails.MINI_KIND);
 //videoModel.setVideoThumb(bmp);

并使用 Glide 直接加载图像缩略图

Glide.with(context).load(new File(videoArrayList.get(i).videoUri.toString())).into(holder.videoThumb);