图库视频缩略图在 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);
我试图在 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);