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

如何解决ListView未仅渲染可见项导致联系人列表加载卡顿的问题

问题根源

卡顿的核心原因是在UI线程同步执行IO操作和Bitmap解码:getView方法运行在UI线程,你每次调用getPhotoAsBitmap都会直接读取系统联系人Provider(IO操作)、解码Bitmap,这两类操作本身就是耗时逻辑,哪怕是加载缩略图,150条数据滚动时频繁同步执行,自然会阻塞UI导致加载慢。


优化方案

1. 异步加载图片,禁止UI线程做耗时操作

不要在getView里同步调用getPhotoAsBitmap,把图片加载逻辑移到后台线程执行:

  • 优先用Glide、Coil等成熟图片加载库,自带线程池、缓存、采样压缩能力,还能自动处理列表滚动时的View复用错位问题,一行代码即可完成联系人头像加载。
  • 如果不想引入第三方库,自行实现时可以用AsyncTask或协程在后台线程加载图片,加载完成后再给ImageView设置,同时需要给ImageView打位置标记,避免滚动复用导致的图片显示错乱。

2. 增加Bitmap内存缓存

用LruCache对已经加载过的联系人头像做内存缓存,缓存大小建议设为应用最大可用内存的1/8,同一个联系人的头像第二次加载时直接从缓存取,不用重复走IO和解码流程,能大幅降低重复加载的耗时。

3. 修正布局inflate的错误写法

你当前的 inflate 逻辑没有正确传入父布局参数,会导致布局根节点的LayoutParams失效,触发额外的测量布局开销,修改为如下写法即可:

convertView = mInflater.inflate(R.layout.contact_with_pic_ex, parent, false);

4. 采样压缩Bitmap,降低解码耗时

加载头像时不需要解码全尺寸图片,可以先读取Bitmap的尺寸参数,再根据ImageView的实际显示大小计算inSampleSize,只解码实际需要的像素大小,既能减少内存占用,也能降低解码耗时。

5. 排查非图片场景的耗时

你提到不加载图片时加载耗时仍有1秒,建议重点排查两点:

  • 联系人数据的查询逻辑是不是在主线程执行?所有数据库、ContentProvider的查询操作都要放到后台线程执行,查询完成后再给ListView设置Adapter。
  • 联系人实体类的get方法有没有额外耗时逻辑?比如getDate是不是每次调用都做字符串格式化?可以提前把需要展示的字段格式化好存在Contact实体中,不要在getView里做重复的字符串处理。

6. 可选长期优化:替换为RecyclerView

RecyclerView的条目复用机制比ListView更高效,还支持局部更新,整体性能优于原生ListView,后续迭代可以考虑替换。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 02:06:05