使用 Glide 冻结 RecyclerView
RecyclerView freezing with Glide
我在游标适配器中使用滑行来加载数千个视图。它们都附有从磁盘加载的小图像(均小于 10kb)。但是我越来越僵硬,问题似乎来自 Glide 库(但它可能是由于 cursorloader)。我在下面附上了我的代码和日志文件。
相关 CursorAdapter 代码:
public FilesFragmentCursorAdapter(Activity context, Cursor cursor, Bucket bucket) {
super(context, cursor, 0);
mContext = context;
this.cursor = cursor;
mBucket = bucket;
mSelectedItemsIds = new SparseBooleanArray();
downloader = new ThumbnailDownloader(mContext, mBucket);
manager = GlideApp.with(mContext);
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mShowThumbnails = mContext.getSharedPreferences(Constants.PREFS, Context.MODE_PRIVATE).getBoolean(Constants.PREFS_SHOW_THUMBNAILS, false);
}
@Override
public Object getItem(int position) {
return super.getItem(position);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
return LayoutInflater.from(context).inflate(R.layout.list_file_item, viewGroup, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
FileViewHolder holder = new FileViewHolder();
holder.mId = view.findViewById(R.id.list_file_id);
holder.mName = view.findViewById(R.id.list_file_name);
holder.mSize = view.findViewById(R.id.list_file_size);
holder.mCreated = view.findViewById(R.id.list_file_date);
holder.image = view.findViewById(R.id.list_file_image);
holder.container = view.findViewById(R.id.list_file_item);
String id = cursor.getString(cursor.getColumnIndex(KEY_PID));
String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
long size = cursor.getLong(cursor.getColumnIndex(KEY_SIZE));
String created = cursor.getString(cursor.getColumnIndex(KEY_CREATED_AT));
String mimeType = cursor.getString(cursor.getColumnIndex(KEY_MIME));
if (id != null) holder.mId.setText(id);
if (name != null) holder.mName.setText(name);
String fileSize = Formatter.formatFileSize(mContext, size);
holder.mSize.setText(fileSize);
if (created != null && created.length() > 10) {
String fileCreatedDate = created.substring(0, 10);
holder.mCreated.setText(fileCreatedDate);
}
if (mimeType != null) {
if (mimeType.contains("image")) {
holder.image.setImageResource(R.drawable.ic_image_black_48dp);
if (mShowThumbnails) {
String thumbnailPath = cursor.getString(cursor.getColumnIndex(KEY_THUMBNAIL));
if (!TextUtils.isEmpty(thumbnailPath)) {
manager.load(thumbnailPath).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).into(holder.image);
} else {
File current = DatabaseHelper.createFileFromCursor(cursor);
downloader.download(current);
}
}
} else if (mimeType.contains("video")) {
holder.image.setImageResource(R.drawable.ic_videocam_black_48dp);
} else if (mimeType.contains("text")) {
holder.image.setImageResource(R.drawable.ic_text_format_black_48dp);
} else if (mimeType.contains("audio")) {
holder.image.setImageResource(R.drawable.ic_audiotrack_black_48dp);
} else {
holder.image.setImageResource(R.drawable.ic_insert_drive_file_black_48dp);
}
}
}
日志:
12-28 21:47:17.212 27355-27450/co.intellidev.storj E/Parcel: fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is 0, fds[i] is -1, fd_count is 1, error: Too many open files
12-28 21:47:20.150 27355-27752/co.intellidev.storj E/libEGL: error creating cache file /data/user_de/0/co.intellidev.storj/code_cache/com.android.opengl.shaders_cache: Too many open files (24)
12-28 21:50:02.744 27355-27450/co.intellidev.storj E/GraphicBuffer: unflatten: registerBuffer failed: Unknown error -5 (5)
12-28 21:50:02.748 27355-27450/co.intellidev.storj E/Surface: dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: 5
12-28 21:50:02.752 27355-27450/co.intellidev.storj E/Parcel: fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is 1, fds[i] is -1, fd_count is 2, error: Too many open files
12-28 21:50:02.752 27355-27450/co.intellidev.storj E/Surface: dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: -22
12-28 21:50:02.754 27355-27450/co.intellidev.storj E/Parcel: fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is 1, fds[i] is -1, fd_count is 2, error: Too many open files
12-28 21:50:02.754 27355-27450/co.intellidev.storj E/Surface: dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: -22
如讨论..
public class FilesFragmentCursorAdapter extends RecyclerView.Adapter<FilesFragmentCursorAdapter.FileViewHolder > {
/* objects */
public FilesFragmentCursorAdapter(Activity context, Cursor cursor, Bucket bucket) {
mContext = context;
this.cursor = cursor;
mBucket = bucket;
mSelectedItemsIds = new SparseBooleanArray();
downloader = new ThumbnailDownloader(mContext, mBucket);
manager = GlideApp.with(mContext);
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mShowThumbnails = mContext.getSharedPreferences(Constants.PREFS, Context.MODE_PRIVATE).getBoolean(Constants.PREFS_SHOW_THUMBNAILS, false);
}
@Override
public FilesFragmentCursorAdapter.FileViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_file_item, parent, false);
return new FileViewHolder(itemView); // <- render view here
}
@Override
public void onBindViewHolder(FilesFragmentCursorAdapter.FileViewHolder holder, final int position) {
String id = cursor.getString(cursor.getColumnIndex(KEY_PID));
String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
long size = cursor.getLong(cursor.getColumnIndex(KEY_SIZE));
String created = cursor.getString(cursor.getColumnIndex(KEY_CREATED_AT));
String mimeType = cursor.getString(cursor.getColumnIndex(KEY_MIME));
if (id != null) holder.mId.setText(id);
if (name != null) holder.mName.setText(name);
}
@Override
public int getItemCount() {
return contactsList.size();
}
public class FileViewHolder extends RecyclerView.ViewHolder {
private TextView mId;
private TextView mName;
private TextView mSize;
// so on
public FileViewHolder (View view) {
super(view);
mId = view.findViewById(R.id.list_file_id);
mName = view.findViewById(R.id.list_file_name);
mSize = view.findViewById(R.id.list_file_size);
// so on
}
}
}
相应地更新您的适配器 class。
我想知道你为什么跳过缓存而不是存储在缓存中。
manager.load(thumbnailPath).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).into(holder.image);
对此进行更改并允许 glide 缓存生成的图像而不是原始图像。
manager.load(thumbnailPath).diskCacheStrategy(DiskCacheStrategy.RESULT).into(holder.image);
我在游标适配器中使用滑行来加载数千个视图。它们都附有从磁盘加载的小图像(均小于 10kb)。但是我越来越僵硬,问题似乎来自 Glide 库(但它可能是由于 cursorloader)。我在下面附上了我的代码和日志文件。
相关 CursorAdapter 代码:
public FilesFragmentCursorAdapter(Activity context, Cursor cursor, Bucket bucket) {
super(context, cursor, 0);
mContext = context;
this.cursor = cursor;
mBucket = bucket;
mSelectedItemsIds = new SparseBooleanArray();
downloader = new ThumbnailDownloader(mContext, mBucket);
manager = GlideApp.with(mContext);
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mShowThumbnails = mContext.getSharedPreferences(Constants.PREFS, Context.MODE_PRIVATE).getBoolean(Constants.PREFS_SHOW_THUMBNAILS, false);
}
@Override
public Object getItem(int position) {
return super.getItem(position);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
return LayoutInflater.from(context).inflate(R.layout.list_file_item, viewGroup, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
FileViewHolder holder = new FileViewHolder();
holder.mId = view.findViewById(R.id.list_file_id);
holder.mName = view.findViewById(R.id.list_file_name);
holder.mSize = view.findViewById(R.id.list_file_size);
holder.mCreated = view.findViewById(R.id.list_file_date);
holder.image = view.findViewById(R.id.list_file_image);
holder.container = view.findViewById(R.id.list_file_item);
String id = cursor.getString(cursor.getColumnIndex(KEY_PID));
String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
long size = cursor.getLong(cursor.getColumnIndex(KEY_SIZE));
String created = cursor.getString(cursor.getColumnIndex(KEY_CREATED_AT));
String mimeType = cursor.getString(cursor.getColumnIndex(KEY_MIME));
if (id != null) holder.mId.setText(id);
if (name != null) holder.mName.setText(name);
String fileSize = Formatter.formatFileSize(mContext, size);
holder.mSize.setText(fileSize);
if (created != null && created.length() > 10) {
String fileCreatedDate = created.substring(0, 10);
holder.mCreated.setText(fileCreatedDate);
}
if (mimeType != null) {
if (mimeType.contains("image")) {
holder.image.setImageResource(R.drawable.ic_image_black_48dp);
if (mShowThumbnails) {
String thumbnailPath = cursor.getString(cursor.getColumnIndex(KEY_THUMBNAIL));
if (!TextUtils.isEmpty(thumbnailPath)) {
manager.load(thumbnailPath).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).into(holder.image);
} else {
File current = DatabaseHelper.createFileFromCursor(cursor);
downloader.download(current);
}
}
} else if (mimeType.contains("video")) {
holder.image.setImageResource(R.drawable.ic_videocam_black_48dp);
} else if (mimeType.contains("text")) {
holder.image.setImageResource(R.drawable.ic_text_format_black_48dp);
} else if (mimeType.contains("audio")) {
holder.image.setImageResource(R.drawable.ic_audiotrack_black_48dp);
} else {
holder.image.setImageResource(R.drawable.ic_insert_drive_file_black_48dp);
}
}
}
日志:
12-28 21:47:17.212 27355-27450/co.intellidev.storj E/Parcel: fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is 0, fds[i] is -1, fd_count is 1, error: Too many open files
12-28 21:47:20.150 27355-27752/co.intellidev.storj E/libEGL: error creating cache file /data/user_de/0/co.intellidev.storj/code_cache/com.android.opengl.shaders_cache: Too many open files (24)
12-28 21:50:02.744 27355-27450/co.intellidev.storj E/GraphicBuffer: unflatten: registerBuffer failed: Unknown error -5 (5)
12-28 21:50:02.748 27355-27450/co.intellidev.storj E/Surface: dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: 5
12-28 21:50:02.752 27355-27450/co.intellidev.storj E/Parcel: fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is 1, fds[i] is -1, fd_count is 2, error: Too many open files
12-28 21:50:02.752 27355-27450/co.intellidev.storj E/Surface: dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: -22
12-28 21:50:02.754 27355-27450/co.intellidev.storj E/Parcel: fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is 1, fds[i] is -1, fd_count is 2, error: Too many open files
12-28 21:50:02.754 27355-27450/co.intellidev.storj E/Surface: dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: -22
如讨论..
public class FilesFragmentCursorAdapter extends RecyclerView.Adapter<FilesFragmentCursorAdapter.FileViewHolder > {
/* objects */
public FilesFragmentCursorAdapter(Activity context, Cursor cursor, Bucket bucket) {
mContext = context;
this.cursor = cursor;
mBucket = bucket;
mSelectedItemsIds = new SparseBooleanArray();
downloader = new ThumbnailDownloader(mContext, mBucket);
manager = GlideApp.with(mContext);
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mShowThumbnails = mContext.getSharedPreferences(Constants.PREFS, Context.MODE_PRIVATE).getBoolean(Constants.PREFS_SHOW_THUMBNAILS, false);
}
@Override
public FilesFragmentCursorAdapter.FileViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_file_item, parent, false);
return new FileViewHolder(itemView); // <- render view here
}
@Override
public void onBindViewHolder(FilesFragmentCursorAdapter.FileViewHolder holder, final int position) {
String id = cursor.getString(cursor.getColumnIndex(KEY_PID));
String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
long size = cursor.getLong(cursor.getColumnIndex(KEY_SIZE));
String created = cursor.getString(cursor.getColumnIndex(KEY_CREATED_AT));
String mimeType = cursor.getString(cursor.getColumnIndex(KEY_MIME));
if (id != null) holder.mId.setText(id);
if (name != null) holder.mName.setText(name);
}
@Override
public int getItemCount() {
return contactsList.size();
}
public class FileViewHolder extends RecyclerView.ViewHolder {
private TextView mId;
private TextView mName;
private TextView mSize;
// so on
public FileViewHolder (View view) {
super(view);
mId = view.findViewById(R.id.list_file_id);
mName = view.findViewById(R.id.list_file_name);
mSize = view.findViewById(R.id.list_file_size);
// so on
}
}
}
相应地更新您的适配器 class。
我想知道你为什么跳过缓存而不是存储在缓存中。
manager.load(thumbnailPath).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).into(holder.image);
对此进行更改并允许 glide 缓存生成的图像而不是原始图像。
manager.load(thumbnailPath).diskCacheStrategy(DiskCacheStrategy.RESULT).into(holder.image);