RecyclerView加载本地歌曲滚动卡顿,如何优化Glide加载?
问题描述
我开发了一个从内存加载歌曲列表的RecyclerView,滚动时存在卡顿问题,仅在每次打开应用后的首次滚动时出现。移除Glide图片加载逻辑后,卡顿现象完全消失。
以下是我的onBindViewHolder实现代码:
override fun onBindViewHolder(holder: MyHolder, position: Int) { holder.titleView.text = musicList[position].title holder.albumName.text = musicList[position].artist holder.duration.text = formatDuration(musicList[position].length) Glide .with(context) .load(musicList[position].artUri) .diskCacheStrategy(DiskCacheStrategy.ALL) .apply(RequestOptions().placeholder(R.drawable.image_as_cover).centerCrop()) .into(holder.imageView) holder.itemView.setOnClickListener { if (MainActivity.isSearching) sendIntent(position = position, parameter = "MusicAdapterSearch") else sendIntent(position = position, parameter = "MusicAdapter") } }
对应列表项的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" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:theme="@style/Theme.Music.Font"> <com.google.android.material.imageview.ShapeableImageView android:id="@+id/imageView" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentStart="true" android:layout_margin="5dp" android:contentDescription="@string/cover" android:src="@drawable/image_as_cover" app:shapeAppearance="@style/roundedImageView" /> <LinearLayout android:id="@+id/linearLayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toStartOf="@+id/duration" android:layout_toEndOf="@+id/imageView" android:orientation="vertical"> <TextView android:id="@+id/titleView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:fontFamily="@font/medium" android:maxLines="1" android:singleLine="true" android:text="@string/love_is_gone_by_slander_forever_on_love" android:textSize="15sp" /> <TextView android:id="@+id/albumName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:fontFamily="@font/medium" android:maxLines="1" android:text="@string/albumName" android:textSize="12sp" android:theme="@style/Theme.Music.FontColor" /> </LinearLayout> <TextView android:id="@+id/duration" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_centerVertical="true" android:layout_margin="10dp" android:fontFamily="@font/medium" android:maxLines="1" android:text="@string/duration" android:textSize="11sp" /> </RelativeLayout>
请问该如何解决此卡顿问题,是否需要更换图片加载库或调整缓存相关策略?
解决方案
不需要更换图片加载库,Glide本身已是优化成熟的图片加载框架,问题出在首次加载的缓存与图片处理策略上,调整以下几点即可解决:
预加载专辑封面
在应用启动阶段(比如MainActivity的onCreate),提前用Glide加载一批常用的专辑封面到内存缓存,避免首次滚动时才触发加载操作。示例代码:// 在初始化时机执行,比如MainActivity.onCreate musicList.take(20).forEach { music -> Glide.with(this) .load(music.artUri) .diskCacheStrategy(DiskCacheStrategy.ALL) .preload(50,50) // 对应列表项中图片的实际尺寸 }优化Glide加载配置
- 明确指定图片加载尺寸,避免Glide自动计算尺寸时的额外性能开销:将
.centerCrop()替换为.override(50,50).centerCrop(),尺寸与布局中ShapeableImageView的宽高保持一致。 - 显式启用内存缓存(Glide默认开启,但显式声明可确保逻辑清晰),添加
.skipMemoryCache(false),让首次加载后的图片存入内存,后续滚动直接读取缓存。
修改后的Glide加载代码:
Glide .with(context) .load(musicList[position].artUri) .diskCacheStrategy(DiskCacheStrategy.ALL) .override(50, 50) // 匹配布局中ImageView的尺寸 .centerCrop() .placeholder(R.drawable.image_as_cover) .skipMemoryCache(false) .into(holder.imageView)- 明确指定图片加载尺寸,避免Glide自动计算尺寸时的额外性能开销:将
优化布局渲染性能
- 将
RelativeLayout替换为ConstraintLayout,相对布局的测量与布局开销在列表场景中更高,约束布局能更高效地处理视图间的位置关系。 - 给
ShapeableImageView添加android:hardwareAccelerated="true"属性,启用硬件加速提升圆角裁剪的渲染效率。
- 将
避免主线程耗时操作
检查formatDuration方法是否在主线程执行了耗时计算,如果是,提前在子线程批量格式化所有歌曲的时长并存入musicList,避免在onBindViewHolder中重复执行计算逻辑。
内容的提问来源于stack exchange,提问作者ShahZaman Rai
相关产品推荐
相关产品推荐

