最近优化了项目里的列表展现,顺便对RecyclerView的使用作了从新的封装,目的是当列表的需求比较复杂的时候,依然可以保持逻辑的清晰和解耦,同时经过封装来使复杂列表的性能获得必定的保证。git
固然若是是很是简单的列表的话,其实Android原生的RecyclerView加上Adapter就已经比较便捷了,没有必要去作过分的封装了。github
项目GitHub地址: github.com/zhengcx/Ins…markdown
每个对项目的重构或者从新封装都是出于对现状的不满,那么咱们就从这个封装项目解决了哪些问题来展开这篇博文吧。oop
须要注意一下你的项目里对列表的使用,特别是加载更多时是否都是重复的全局刷新,这对复杂列表的性能影响较大,你须要考虑每次刷新不去刷新那些不须要刷新的item,一个是对性能会有提升,另外一个页面上用户的体验也会好不少,本项目提供了全局刷新和增量刷新的相关方法,保证加载更多或者操做单个item时只局部刷新。布局
RecyclerView自己并无提供像ListView那样便捷的添加header/footer的方法,因此须要咱们本身去实现。性能
网上主要有两种:一种是采用wrap的方式使header、footer和普通item区别开,而另外一种方式使把header、footer也当作是一种itemType来作。优化
这里咱们采用了第二种方式,提供了便捷添加header/footer的方法,固然把header\footer当作一种itemType来看待,则当header/footer发生增删(特别是header)时,则会使列表发生全局的刷新,这里优化的点是对RecyclerView来讲他的header永远只有一个,是一个ViewGroup,以后要添加或者删除一个或多个header,都只是往这个ViewGroup里增删View,将不会对整个列表产生刷新,提供性能和体验。spa
当你的列表会存在多种复杂的itemType时,很容易时Adapter里的代码产生混乱,且不够清晰,很难拓展。咱们封装的目的是:code
1.让每种itemType的处理逻辑交给各自的itemDelegate去处理,实现不一样itemType处理逻辑的解耦orm
2.让代码易于拓展,也就是说无论从此要再添加多少种itemType,都能作到很是清晰,很是便捷。
项目里经过DelegateScheduler来管理调度不一样itemType的处理逻辑,使多itemType变得清晰易拓展。
咱们的列表一般都须要好几种显示加载状态的View,好比loadingView、加载失败View、加载数据为空View。若是你的作法是在布局文件里先写好这几种View而后经过设置是否可见来控制,显然这会引发布局嵌套过渡绘制的问题,固然你能够利用ViewStub来作一些优化,可是治标不治本,当这些状态View被inflate一次后,依然会存在这种问题。
若是你把这些状态View也当作是一种itemType呢,让它与普通item同样参与回收,参与cache,是否是就能够解决这个问题,这是我目前看到想到的比较理想的方式,固然可能有更好的方式。
显然若是你把上拉加载更多这个功能放在你的业务代码里去监听是不合适的,咱们须要封装一下,让recyclerView自动就带有这个功能,直接使用就能够了。
本项目给上拉加载更多提供了两种不一样的监听方式,看我的喜爱本身选择。
1.实时监听,也就是说只要用户滑动,那么就会实时监听判断要不要开始加载下一页数据,这一种的好处是让列表预加载更加实时,基本能够实时用户能够不断的下拉,使用户感知不到咱们的加载过程。
2.另外一种是只有当列表滚动状态发生改变时才会发起是否加载下一页数据的判断,这一种基本是用户从滑动到中止时才会发起下一页的加载。
固然两种方式提早多少个item发起预加载下一页都是能够由你本身来设置这个参数,目前默认是采用第二种方式,能够经过设置来使用第一种方式。
RecyclerView没有像ListView那样提供setOnItemCLickListener()方法来绑定item的点击事件,因此咱们通常都会本身去设置这个item的点击事件,这样子很容易就把点击事件屡次重复设置了。
这里封装提供了setOnItemClickListener()方法,让你能够放心的设置item点击事件,而且在回调里提供该item所绑定的数据,以及item的position,该item的类型等重要信息,可使你在多种itemType的列表里的点击事件里正确的作各类你想作的事情。
其实对于一些复杂的列表,性能问题显得尤其重要,上面说了一个是尽可能去作局部刷新而不是全量刷新,一个是尽可能减小过分绘制。还有一个很是重要的是每一个版本都要去关注你的bindViewHolder()里的逻辑是否有耗时严重的方法或操做,列表性能出现问题,很大几率就是你的bindViewHolder()中有叫耗时操做,排查也很好排查,经过SysTrace+TraceView能够很快找到耗时的方法和性能的瓶颈,而后作针对性的优化就能够了。
项目GitHub地址: github.com/zhengcx/Ins…
最后,但愿世界上的每个列表都丝丝如滑~~~