这里只谈优化,不讲实现,因为网上太多优化方式的实现了,废话不多说,现在进入正题
优化方式一:DiffUtil的使用
DiffUtil的使用,其方式就是在程序用拥有两个数据集,在进行刷新的时候会比较用新数据集比较旧数据集,只刷新产生变化的数据,不会全部刷新item,这个功能是在android7.0 之后才有的。关于DiffUtil更详细的去查看这篇文章
优化方式二:重写onScroll事件
对于有大量图片加载的recyclerView,滑动的时候暂停加载图片,当且仅当界面停止滑动的时候加载图片,中间过渡阶段的图片用户不会看,所以就没必要每张图片都加载出来。
优化方式三:recyclerView数据预取
android SDK >= 21时,支持渲染(render)线程,recyclerView数据显示分两个阶段
1、在UI线程,处理输入事件、动画、布局、记录绘画操作,每一个条目在进入屏幕显示之前都会被创建和绑定view;
2、渲染(render)线程把指令送往GPU
数据预取的思想就是:将闲置的UI线程利用起来,提前计算下一帧的Frame buffer
优化方式四:设置 recyclerView.setHasFixedSize(true);
当item的高度如是固定的,设置这个属性为true可以提高性能,尤其是当recyclerView有条目插入、删除时性能提升更明显。
recyclerView在条目数量改变,会重新测量、布局各个item,如果设置了setHasFixedSize(true),由于item的宽高都是固定的 ,adapter的内容改变时,recyclerView不会对整个布局都重绘。
void onItemInsertedOrRemoved(){
if(hasFixedSize) layoutChildren;
else requestLayout();
}
优化方式五:使用getExtraLayoutSpace为LayoutManager设置更多的预留空间
在recyclerView的元素比较高,一屏只能显示一个元素的时候,第一次滑动到第二个元素会卡顿。
recyclerView(以及其他基于adapter的view,比如listView,GridView等)使用了缓存机制重用子view(即系统只将屏幕可见范围之内的元素保存在内存中,在滚动的时候不断的重用这些内存中已经存在的view,而不是新建view)。
这个机制会导致一个问题,启动应用之后,在屏幕可见范围内,如果只有一张卡片可见,当滚动的时候,recyclerView找不到可以服用的view了,他将创建一个新的,因此在欢动到第二个feed的时候就会有一定的延时,但是第二个feed之后的滚动是流畅的,因为这个时候recyclerView已经有能够重用的view了。
如何解决这个问题呢,其实只需要重写getExtraLayoutSpace()方法,根据官方文档的描述getExtraLayoutSpace将返回layoutManager应该预留的额外空间(显示范围之外,应该额外缓存的空间)
LinearLayoutManager linearLayoutManager = new LinearLayoutManger(this){
@override
protected int getExtraLayoutSpace(RecycleView.State state){
return 300;
}
}
优化方式六:局部刷新
notifyDataSetChanged会触发所有item的detached回调,再触发onAttach回调,我们可以根据场景适当的选用
notifyItemChanged(int position)
notifyItemInserted(int position)
notifyItemRemoved(int position)
notifyItemMoved(int fromPosition, int toPosition)
notifyItemRangeChanged(int positionStart, int itemCount)
notifyItemRangeInserted(int positionStart, int itemCount)
notifyItemRangeRemoved(int positionStart, int itemCount)
如果必须用 notifyDataSetChanged(),那么最好设置 mAdapter.setHasStableIds(true)
setHasStableIds(true)的作用:在数据刷新的时候,防止焦点丢失
这里的内容我是通过这里android每日一面试题 学习汇总的,这里面的问题可以帮助开发者回忆一些知识点,非常良心!!!