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

加载Bitmap时RecyclerView滚动卡顿,Glide加载PDF转Bitmap列表怎么优化滑动

RecyclerView加载PDF预览图卡顿优化方案

卡顿核心原因

  • 你当前在主线程执行pdfToBitmap转换逻辑,PDF渲染属于重度耗时操作,直接阻塞主线程导致掉帧
  • 生成的Bitmap使用PDF原尺寸,远大于列表ImageView的实际展示尺寸,占用内存过高,频繁触发GC导致卡顿
  • 直接传入Bitmap给Glide加载,Glide无法直接关联PDF文件做缓存,每次滑动都要重新转换Bitmap,重复消耗资源

优化方案

1. 不要在主线程执行PDF转换逻辑

绝对不要在onBindViewHolder中同步调用pdfToBitmap方法,将转换逻辑放到异步线程执行,最优方案是通过Glide自定义ModelLoader,让Glide在自身维护的异步线程池中完成转换,同时自动复用缓存机制。

2. 优化PDF转Bitmap逻辑,按目标尺寸采样

不要使用PDF原宽高生成Bitmap,按实际要展示的ImageView尺寸缩放,大幅降低内存占用,优化后的转换代码如下:

public static Bitmap pdfToBitmap(File pdfFile, int targetWidth, int targetHeight) {
    Bitmap bitmap = null;
    ParcelFileDescriptor fd = null;
    PdfRenderer renderer = null;
    PdfRenderer.Page page = null;
    try {
        fd = ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY);
        renderer = new PdfRenderer(fd);
        if (renderer.getPageCount() <= 0) {
            return null;
        }
        page = renderer.openPage(0);
        // 计算适配目标尺寸的最小缩放比例,避免生成过大Bitmap
        float scale = Math.min((float) targetWidth / page.getWidth(), (float) targetHeight / page.getHeight());
        int width = Math.round(page.getWidth() * scale);
        int height = Math.round(page.getHeight() * scale);
        bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
        return bitmap;
    } catch (Exception ex) {
        if (bitmap != null) bitmap.recycle();
        ex.printStackTrace();
        return null;
    } finally {
        if (page != null) page.close();
        if (renderer != null) renderer.close();
        try {
            if (fd != null) fd.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3. 调整Glide加载逻辑,启用缓存

直接将PDF文件作为输入源传给Glide,不要提前转Bitmap,同时配置缓存策略,避免重复转换:

Glide.with(viewHolder.itemView.getContext())
     .load(pdfFile) // 直接传入PDF文件对象
     .override(200, 300) // 按列表预览图的实际固定尺寸填写,避免动态测量耗时
     .diskCacheStrategy(DiskCacheStrategy.RESOURCE) // 缓存转换后的Bitmap
     .placeholder(R.drawable.your_placeholder) // 增加占位图,避免滑动时留白
     .into(viewHolder.pdfImg);

4. RecyclerView基础配置优化

  • 给RecyclerView设置setHasFixedSize(true),避免重复测量布局
  • 开启列表预加载:recyclerView.setInitialPrefetchItemCount(4)
  • 滑动时暂停Glide加载,减少滑动时的资源占用:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        if (newState == RecyclerView.SCROLL_STATE_FLING) {
            Glide.with(recyclerView.getContext()).pauseRequests();
        } else {
            Glide.with(recyclerView.getContext()).resumeRequests();
        }
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 17:15:03