在网上关于RecyclerView的基本使用方式已经有了比较详细介绍,并且其设计结构也相似于ListView,因此本文将不重点介绍如何使用,在文末的引用中均可以相关内容。这里主要是介绍RecyclerView的基本功能、设计理念,以及系统提供API的状况。android
RecyclerView是在Android L(也就是后来的Lollipop)中新加入的一种ViewGroup。但由于它使以support-v7库的形式加入到Android系统中,因此不只仅是Lollipop版本之后的Android系统可使用,只要系开发项目中引入这个库就在任意API级别中使用。git
单从呈现效果来看RecyclerView和ListView、GridView并无大多的差异。github
不过它的“flexible”并不仅仅指它能够在ListView和GridView之间随意互相切换,更在于它能够创造出更多的复杂的可滚动的视图,好比水平方向的ListView,或者是Web上很流行的瀑布流式布局(Masonry)。只是大部分布局系统都没有提供,必须由开发者本身实现。布局
因此RecyclerView的“flexible”:什么均可以作,但什么都要本身作。flex
只要用Android提供的LieanerLayoutManager并配以VERTICAL模式,RecyclerView就能够完美达到ListView的基本效果。二者的设计结构也都是数据(Dataset)与视图(View)分离,而后经过适配器(Adapter)来链接的方式。动画
但RecyclerView相对ListView来讲有如下几大提高:spa
ListView从它的父类AdapterView直接继承了对子项目点击的响应,开发者能够定义本身的OnItemClickListner来接受点击事件。但这个设计也形成了一些问题,好比子项内部视图若是设置了OnClickListener,那么子项目视图自己并不会知道,从而可能会致使视图点击状态没有同步等问题。ReyclerView没有提供简便的响应子项目被点击的监听器,虽然它有一个OnItemTouchListener,但在这个接口方法中没有任何关于那个子项目被点击的信息,该接口只是帮助开发者截获触摸事件,对于如何处理,检测被触摸目标对象都留给了开发者去完成。设计
ListView作到了数据和视图的分离,RecyclerView在视图和布局之间再进一步分离,因而便有了LayoutManager。RecyclerView负责管理视图的重复利用,而后将布局方式全权交给了LayoutManager,经过配置或者切换LayoutManager就能够得到不一样的布局效果。不像ListView被限制在垂直滚动布局。同时RecyclerView还提供了ItemDecoration,在已有的子视图基础上还能够添加额外的视图。好比作一条分割线,在ListView就须要额外占用一个ViewType来提供视图,如今则不须要在Adapter中加入这些与实际逻辑业务无关的辅助内容。code
ListView也能够支持子项目层次的动画效果,在Android Developers的DevBytes频道里有不少关于这方面的介绍,不过在看过其实现以后就会发现其解决方案是多么的丑陋而冗长。不少时候都是在计算和分析子视图的位置状态。RecyclerView则带来了很是简洁的ItemAnimator接口。当Adapter中的数据发生“增删改移”变化,经过调用Adapter相应的方法就能够激活动画的产生。固然开发者还须要本身实现具体的ItemAnimator对象来完成所需的动画效果,可是其清晰的结构和接口已比ListView有极大的进步。对象
上边提到RecyclerView的套件已经加入了Support Library v7,并且是以单独的库放入,因此只要在Android Studio项目的Gradle编译文件的dependencies下加入下边的这句就能够开始使用RecyclerView了:
compile 'com.android.support:recyclerview-v7:25.x.x'
不过看过库中提供的那些自带对象实现,体现基本操做流程,就会发现RecyclerView能作的看起来不少,可是已经作到的实在太少。
RecyclerView提供了一个抽象Adapter类,而后就没有了。没有任何能够直接使用的子类,像ListAdapter那样的ArrayAdapter、SimpleCursorAdapter现成的类都没有。一切都留给开发者本身去实现定义。
仔细想一想这也很挺正常,相信应该不多在实际产品中有使用ArrayAdapter的,由于大部分列表都不会是简单的一行文字。对于CursorAdapter使用也每每会实现不一样的继承类来提供子视图。再者RecyclerView的Adapter和ListAdapter在理念上仍是同样的,因此想实现个RecyclerViewCursorAdapter,直接从CursorAdapter取材即可。
RecyclerView的Adapter相对ListAdapter在接口上有几处变化也值得注意。
首先其将getView()方法分拆成了createViewHolder()和bindViewHolder()两个。不过这个没有什么好紧张的,在CursorAdapter里就已经有见到过这个更加合理的设计。另外返回对象也从View变成了ViewHolder只需提一下。
最关键的注意点在于createViewHolder(ViewGroup parent, int viewType)第二参数虽然是整形,可是它并非以往的当前子项的位置(position),而是调用getItemViewType()得到的的子项的类别。彷佛在建立ViewHolder时,RecyclerView故意在隐藏子项的详细信息,但愿开发者彻底只依赖其类别来建立相应的View以及ViewHolder。
其次,RecyclerView的Adapter除了和ListAdapter同样有notifyDataSetChanged()方法外,还有一堆会触发动画效果的通知数据改变的方法:
调用这些方法就会激发ItemAnimator上对应的用于产生动画的方法。
在ListView的年代里,其实已经在使用ViewHolder,只是那时的方法看起来比较讨巧,要隐藏在View的Tag()里。如今RecyclerView强制使用ViewHolder,而且ViewHolder除了有对子视图的引用,还有诸如ItemViewType和Position这些信息。
mHolder.getItemViewType(); // 获取当前Holder类型
mHolder.getAdapterPosition(); // 获取当前的position(当有删除/新增item时,会时时更新),所以可替代经过Tag获取数据。
LayoutManager相对于ListView来讲是一个新部分,经过继承该类来实现自定义的布局方式,而不像ListView只有固定的布局方式。Support库提供了两个现成的子类:LinearLayoutManager和StaggeredGridLayoutManager。前者能够得到和ListView同样的布局,还能够是水平方向的;后者则提供了形如GridView的布局。因此应用程序中的基本平常因此均可以被知足。
若是须要实现自定义的LayoutManager,就比较麻烦了,须要理解Recycle、Scrap、Dirty这些关于子项目视图状态的概念。
经过继承实现ItemAnimator,而后建立对象设置到RecyclerView上就能够获得基于子项目的动画效果。不过如何正确合理地建立一个ItemAnimator子类,却没有详细的描述指南。
库中提供的惟一一个可用的子类DefaultItemAnimator,能够看出它的动画效果是简单的Alpha渐变。同时也会发现其实现是如此的复杂,有不少对于动画步骤的操做,还得注意动画在中途被打断的处理,在结束时也要重置视图状态以便重用。这也反过来讲明ItemAnimator基本没有提供任何关于如何实现和管理动画的信息。另外一方面由于DefaultItemAnimator的实现过于具体,所以它并非合适做为自定义ItemAnimator的父类。
相信当RecyclerView愈来愈多的被应用到程序中时,更多关于这方面的合理设计会被提出来。目前在Github上也有很多参考了DefaultItemAnimator的实现方式,好比RecyclerViewItemAnimators、recyclerview-animators。
关于ItemAnimator的使用,有几点值得提醒的是:若是没有提供ItemAnimator,RecyclerView默认会建立一个DefaultItemAnimator用于动画,因此不须要显示地设置DefaultItemAnimator对象到RecyclerView上;添加(add)和删除(remove)是默认起效的,可是修改(change)的效果须要调用setSupportsChangeAnimations(boolean)来指定是否启用,其默认是没有修改的动画。
整体而言,RecyclerView的功能很是强大,其结构设计也十分开放,这也形成它的上手使用相对比较困难。随着愈来愈多的人开始尝试使用这个部件,也会有愈来愈深入的理解和设计实现。另外,阅读RecyclerView的源码能够帮助对其设计思想的了解,在之后设计其它的复用视图时能够有更好的参照。