您的位置:首页 > 其它

RecyclerView初探

2015-08-05 10:18 316 查看
出自:http://blog.csdn.net/wanglu198506/article/details/43898131 ,这应该是初步了解RecyclerView全貌的最佳文章。

原文地址:http://www.grokkingandroid.com/first-glance-androids-recyclerview/

RecyclerView是去年谷歌I/O大会上随Android L预览一起发布的,接下来的几篇译文将会从各个方面对RecyclerView做一个全面的介绍:

本文示例代码项目地址:https://github.com/writtmeyer/recyclerviewdemo


为什么叫RecyclerView?

谷歌在Android L预览版API文档中是这样描述的:

一个非常灵活的用于在有限的窗口范围内显示大量数据的控件。

所以RecyclerView适用于那些有大量同类的View但是不能同时在屏幕中显示的情况,比如联系人、用户列表、音乐文件列表等等。想看到更多信息需要滚动试图,同时对离开屏幕的视图进行回收和重用。

以下图片解释了这个过程:左边是应用程序的初始状态,当向上滚动视图的时候,一些子View准备被回收,比如右边的红框部分中的两个不可见的View。现在回收器可以把他们放入准备重用的View的列表以便在适当的时候重用。



对View的回收重用是非常有用的,由于不用每次都重新填充布局,这样可以节约CPU资源;同时由于不用保存大量的不可见的视图,也有效的节省了内存资源。

看到这里可能有人要说,这个概念早就有了,ListView就是使用这样的机制。是的没错,但是在ListView中,控件外观、回收过程和其他操作是紧耦合的,缺乏灵活性,这就是为什么谷歌要开发RecyclerView来取代它的意义所在。


RecyclerView本身不关心视图相关的问题

由于ListView的紧耦合问题,谷歌的改进就是RecyclerView本身不参与任何视图相关的问题。它不关心如何将子View放在合适的位置,也不关心如何分割这些子View,更不关心每个子View各自的外观。进一步来说,RecyclerView只负责回收和重用的工作,这就是它名字的由来。

所有关于布局、绘制和其他相关的问题,也就是跟数据展示相关的所有问题,都被委派给了一些”插件化”的类来处理。这使得RecyclerView的API变得非常灵活。你需要一个新的布局么?接入另一个LayoutManager就可以了!你想要不同的动画么?接入一个新的ItemAnimator就可以了,诸如此类。

以下是RecyclerView中用于数据展示的一些重要的类,他们都是RecyclerView的内部类:

Adapter:包装数据集合并且为每个条目创建视图。

ViewHolder:保存用于显示每个数据条目的子View。

LayoutManager:将每个条目的视图放置于适当的位置。

ItemDecoration:在每个条目的视图的周围或上面绘制一些装饰视图。

ItemAnimator:在条目被添加、移除或者重排序时添加动画效果。

下面将对这些类进行分别介绍:


RecyclerView.ViewHolder

ViewHolder的基本作用是缓存视图对象,Android官方很早钱就推荐使用ViewHolder的编程模式,但是现在使用这种模式将是强制性的。

RecyclerView.ViewHolder的子类都可以通过ViewHolder的public的成员变量itemView来访问每个条目的根视图,所以ViewHolder子类中不需要在保存这个视图。

以下是ViewHolder的示例代码:


RecyclerView.Adapter

Adapter充当两个角色:访问数据集合以及负责为每个条目创建正确的视图。Adapter在Android中经常出现,比如ListView、AutoCompleteTextView、Spinner等,他们都继承自AdapterView,但是RecyclerView并没有这样做。

对于RecyclerView,谷歌决定使用新的RecyclerView.Adapter基类来取代旧的Adapter接口。所以,SimpleCursorAdapter、ArrayAdapter都将成为历史,或者至少不会是他们现在的这种使用方式。

目前RecyclerView.Adapter还没有默认实现,以后可能会添加。由于RecyclerView.Adapter是一个抽象类,所以必须要实现以下三个方法:

public VH onCreateViewHolder(ViewGroup parent, int viewType)

public void onBindViewHolder(VH holder, int position)

public int getItemCount()

其中VH是泛型类,当继承RecyclerView.Adapter时需要使用具体的类来替换。Adapter的示例代码如下:


RecyclerView.LayoutManager

LayoutManager可能是RecyclerView中最有趣的部分了,该类负责放置所有的子View到适当位置。该类有一个默认的实现:LinearLayoutManager,当要实现水平或垂直列表时可以使用该类。

更正,作者写这篇文章的时候确实只有LinearLayoutManager, 现在又增加了StaggeredGridLayoutManager。

必须要给RecyclerView设置一个LayoutManager,否则会抛出异常:

目前LayoutManager只有一个抽象方法:

public LayoutParams generateDefaultLayoutParams()

但是还有一个方法需要重写,因为这个方法很快就要变成抽象的了:

但是只重写以上两个方法还远远不够,毕竟LayoutManager的责任是放置所有子View到适当的位置上,所以还需要重写onLayoutChildren()方法:


LinearlayoutManager

LinearLayoutManager是目前LayoutManager唯一的默认实现,可以用来创建水平或者垂直列表。

LinearLayout非常复杂,这里只简单谈谈其中一些关键部分。LinearLayoutManager的用法是非常简单的:初始化它,然后设置一个方向(水平/垂直)就可以了:

LinearLayoutManager还提供了一些方法用来查找当前屏幕上的第一个和最后一个条目:

findFirstVisibleItemPosition()

findFirstCompletelyVisibleItemPosition()

findLastVisibleItemPosition()

findLastCompletelyVisibleItemPosition()


RecyclerView.ItemDecoration

使用ItemDecoration可以给每个条目添加偏移量、可以给条目间添加间距或者高亮条目,添加其他修饰效果等等。

ItemDecoration并不是必须使用的,例如可以使用CardView作为每个条目的视图。

另外,可以添加任意数量的ItemDecoration,RecyclerView会遍历所有的ItemDecoration然后按适当顺序调用每一个的绘制方法

ItemDecoration虚基类包含以下三个方法:

public void onDraw(Canvas c, RecyclerView parent)

public void onDrawOver(Canvas c, RecyclerView parent)

public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent)

onDraw中绘制的内容可能会被条目内容所覆盖,如果要在条目上绘制内容需要使用onDrawOver()方法。如果需要条目间距来绘制分割线,那么使用以上两个方法的差别不大,但是如果真的要添加装饰效果,还是需要使用onDrawOver()。

LayoutManager在测量阶段会调用getItemOffset()方法来正确计算每个条目视图的大小。outRect参数可能第一眼看来有些奇怪,为什么不使用一个返回值呢?但是这样的参数设置确实是有意义的,它使得对于所有的子视图RecyclerView可以重用同一个Rect对象,节省了资源开销。这并不是必须的,但确实是很有效率的。


RecyclerView.ItemAnimator

ItemAnimator可以为每个条目添加动画效果,它主要处理以下三种事件:

An item gets added to the data set

An item gets removed from the data set

An item moves as a result of one or more of the previous two operations

ItemAnimator有一个默认实现:DefaultItemAnimator,如果没有设置自定义的ItemAnimator,RecyclerView就会使用默认的DefaultItemAnimator。

显然如果要让动画生效,需要知道数据集合的变化,这需要Adapter的帮助。在之前的版本中,当变化发生改变时,需要调用notifyDataSetChanged()方法。但这是不合适的,因为这个方法会触发对于所有可视子View的重绘,而且没有动画效果。要看到动画效果需要使用更加特殊的方法:

RecyclerView.Adapter类包含很多notifyXXX()类型的方法,两个最常用的是:

public final void notifyItemInserted(int position)

public final void notifyItemRemoved(int position)


监听器

RecyclerVIew提供了一些非常通用的监听器。之前常见的那些使用方式现在都不适用了,RecyclerView没有提供OnItemClickListener或者OnItemLongClickListener。但是可以使用RecyclerView.OnItemTouchListener结合手势监听来处理这些事件。需要的编码工作必之前达到同样的效果要多。


把以上所有类结合起来

布局文件:

RecyclerView的AttributeSet会在generateLayoutParams()方法中使用:

程序代码部分很简单:

主要步骤如下:

获取RecyclerView的引用

创建一个LayoutManager并添加

创建一个Adapter并添加

如果需要的话,创建1个或多个ItemDecoration并添加

如果需要的话,创建ItemAnimator并添加

如果需要的话,创建1个或多个监听器并添加

当然这只是初步的代码,真正有趣的部分在于RecyclerView有很多内部类,可以用来继承并且实现各种自定义的效果,这才是真正需要投入大量工作的地方。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: