You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android文件夹图片视频列表滚动卡顿,求优化显示方案

解决RecyclerView展示图片/视频缩略图卡顿的优化方案

兄弟,滚动卡顿这个问题太常见了,看了你贴的代码,问题主要出在主线程同步加载缩略图和没有缓存机制这两点上——每次滚动到视频Item时,你都在UI线程里调用ThumbnailUtils.createVideoThumbnail生成缩略图,这可是实打实的耗时操作,直接把UI线程卡得动弹不得。而且每次复用ViewHolder都要重新生成一遍,完全是重复劳动,不卡才怪!

下面给你几个针对性的优化方案,从易到难,你可以按需选择:

1. 直接用成熟的图片加载库(最推荐,省心省力)

像Glide、Picasso这类库本身就封装了异步加载、内存/磁盘缓存、自动复用等优化逻辑,处理视频缩略图也不在话下,完全不用自己造轮子。

比如用Glide实现的话,把你原来的代码改成这样就行:

public void onBindViewHolder(@NonNull DetailViewHolder holder, final int position) {
    String filePath = listFile.get(position).toString();
    if (filePath.endsWith("mp4")) {
        // 用Glide加载视频缩略图
        Glide.with(mContext)
             .asBitmap()
             .load(Uri.fromFile(new File(filePath)))
             .placeholder(R.drawable.default_video_placeholder) // 加载时的占位图
             .error(R.drawable.load_error) // 加载失败的占位图
             .into(holder.ivIcon);
        holder.ivPlay.setVisibility(View.VISIBLE);
    } else {
        // 图片的话直接加载
        Glide.with(mContext)
             .load(Uri.fromFile(new File(filePath)))
             .placeholder(R.drawable.default_image_placeholder)
             .into(holder.ivIcon);
        holder.ivPlay.setVisibility(View.GONE);
    }
}

Glide会自动帮你:

  • 在后台线程生成/加载缩略图,不阻塞UI
  • 缓存生成好的缩略图,下次滚动直接取缓存
  • 根据ImageView的大小自动压缩图片,减少内存占用

2. 自己实现异步加载+缓存(适合不想依赖第三方库的场景)

如果不想引入第三方库,那至少要把缩略图的生成放到异步线程,同时加上内存和磁盘缓存:

第一步:用异步线程生成缩略图

可以用AsyncTask或者ExecutorService来做后台任务,比如:

private class LoadThumbnailTask extends AsyncTask<String, Void, Bitmap> {
    private WeakReference<ImageView> imageViewRef;
    private String filePath;

    public LoadThumbnailTask(ImageView imageView, String filePath) {
        this.imageViewRef = new WeakReference<>(imageView);
        this.filePath = filePath;
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        // 后台生成缩略图
        return ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.MINI_KIND);
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        super.onPostExecute(bitmap);
        ImageView imageView = imageViewRef.get();
        if (imageView != null && bitmap != null) {
            imageView.setImageBitmap(bitmap);
        }
    }
}

然后在onBindViewHolder里调用:

public void onBindViewHolder(@NonNull DetailViewHolder holder, final int position) {
    String filePath = listFile.get(position).toString();
    if (filePath.contains("mp4")) {
        holder.ivPlay.setVisibility(View.VISIBLE);
        // 先设置占位图
        holder.ivIcon.setImageResource(R.drawable.default_video_placeholder);
        // 启动异步任务加载缩略图
        new LoadThumbnailTask(holder.ivIcon, filePath).execute();
    }
}

第二步:添加缓存机制

用LruCache做内存缓存,把生成好的缩略图存起来,下次直接取:

private LruCache<String, Bitmap> thumbnailCache;

// 在初始化的时候设置缓存大小,比如内存的1/8
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
int cacheSize = maxMemory / 8;
thumbnailCache = new LruCache<String, Bitmap>(cacheSize) {
    @Override
    protected int sizeOf(String key, Bitmap bitmap) {
        // 返回Bitmap的大小(KB)
        return bitmap.getByteCount() / 1024;
    }
};

// 存缓存
private void addBitmapToCache(String key, Bitmap bitmap) {
    if (getBitmapFromCache(key) == null) {
        thumbnailCache.put(key, bitmap);
    }
}

// 取缓存
private Bitmap getBitmapFromCache(String key) {
    return thumbnailCache.get(key);
}

然后在异步任务里先查缓存,没有再生成:

@Override
protected Bitmap doInBackground(String... params) {
    Bitmap cachedBitmap = getBitmapFromCache(filePath);
    if (cachedBitmap != null) {
        return cachedBitmap;
    }
    Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.MINI_KIND);
    addBitmapToCache(filePath, bitmap);
    return bitmap;
}

3. RecyclerView本身的基础优化

除了缩略图加载,RecyclerView本身也可以做一些优化来提升流畅度:

  • 给RecyclerView设置setHasFixedSize(true),如果你的列表高度是固定的,这样可以减少布局重计算
  • 避免在onBindViewHolder里做任何耗时操作,除了绑定数据
  • 优化Item布局,减少嵌套层级,用ConstraintLayout代替嵌套的LinearLayout/RelativeLayout,降低过度绘制
  • 如果不需要Item动画,可以关闭默认动画:recyclerView.setItemAnimator(null);

最后再提醒一句,自己写缓存和异步很容易踩内存泄漏、重复加载的坑,还是优先用Glide这类成熟库,省心又靠谱!

内容的提问来源于stack exchange,提问作者A2N

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:58:26