recyclerView 列表类控件卡顿优化
1、使用ConstraintLayout减少布局层级。
2、可以的话,设置RecyclerView布局等高,然后设置recyclerView.setHasFixedSize(true)
这样可以避免每次绘制Item时,不再重新计算Item高度。
3、根据需求修改RecyclerView默认的绘制缓存选项
recyclerView.setItemViewCacheSize(20);
recyclerView.setDrawingCacheEnabled(true);
recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
4、在onBindViewHolder/getView方法中,减少逻辑判断,减少临时对象创建。例如:复用事件监听,在其方法外部创建监听,可以避免生成大量的临时变量。
减少逻辑判断参考方案:
//优化前:
class MyRecyclerView.Adapter extends RecyclerView.Adapter {
static final TODAYS_DATE = new Date();
static final DATE_FORMAT = new SimpleDateFormat("MM dd, yyyy");
public onBindViewHolder(Task.ViewHolder tvh, int position) {
Task task = getItem(position);
if (TODAYS_DATE.compareTo(task.dateDue) > 0) {
tvh.backgroundView.setColor(Color.GREEN);
} else {
tvh.backgroundView.setColor(Color.RED);
}
String dueDateFormatted = DATE_FORMAT.format(task.getDateDue());
tvh.dateTextView.setDate(dueDateFormatted);
}
}
//优化后,改写model
public class TaskViewModel {
int overdueColor;
String dateDue;
}
public onBindViewHolder(Task.ViewHolder tvh, int position) {
TaskViewModel taskViewModel = getItem(position);
tvh.backgroundView.setColor(taskViewModel.getOverdueColor());
tvh.dateTextView.setDate(taskViewModel.getDateDue());
}
6、避免整个列表的数据更新,只更新受影响的布局。例如,加载更多时,不使用notifyDataSetChanged()
,而是使用notifyItemRangeInserted(rangeStart, rangeEnd)
7、scrollingCache=false
animationCache=false
(针对ListView)
scrollingCache: scrollingCache本质上是drawing cache,你可以让一个View将他自己的drawing保存在cache中(保存为一个bitmap),这样下次再显示View的时候就不用重画了,而是从cache中取出。默认情况下drawing cahce是禁用的,因为它太耗内存了,但是它确实比重画来的更加平滑。而在ListView中,scrollingCache是默认开启的,我们可以手动将它关闭。
animateCache: ListView默认开启了animateCache,这会消耗大量的内存,因此会频繁调用GC,我们可以手动将它关闭掉。
8、对于RecyclerView,持有item具有的独特id,可以很容易地确定具体item并单独更新,当变化发生时,可以按照如下方式更新,从而避免整体刷新:
adapter.setHasStableIds(true);
adapter.notifyItemRemoved(position);
adapter.notifyItemChanged(position);
adapter.notifyItemInserted(position);