android v7兼容包RecyclerView的使用(二)
2015-03-11 20:30
387 查看
上篇文章 android v7兼容包RecyclerView的使用(一)讲了RecyclerView的最基本用法,现在开始挖掘更详细的内容。
在RecyclerView的API中,有这样一句话
A flexible view for providing a limited window into a large data set.
大致意思就是:当有大量的数据显示在一个有限大小的窗口上时,RecyclerView就是解决这种情况的一个灵活的View。
从以上描述可以看出RecyclerView的使用场景。如果我们有大量的同一类型的数据要显示在屏幕上,而此时很有可能整个屏幕无法完全显示所有的数据,这时候RecyclerView就是一个合适的选择。当用户上下滚动屏幕的时候,item的循环重复利用也在同时进行,当一个新的item进入可视范围,必然有一个旧的item移出可视范围,而这个被移出的item也就被循环重用。那么循环重用item有什么作用呢,其实他是很有用的一种方法,因为它节省了CPU资源和内存。
或许你会说我们用ListView用了很长的时间了,RecyclerView与我们以前的方式有什么特别的地方呢,从前,我们使用listview的时候,显示,循环重用以及其它的一些东西都有一定程度上的耦合性,现在RecyclerView则提供了一种更加灵活的方式。
谷歌现在使用的这种方法,它不在乎RecyclerView所看到的东西,也不在乎元素是否显示在正确的地方,更不在乎每个元素是如何分隔的。RecyclerView做的事仅仅是是回收。因此得名RecyclerView。
下面是几个和RecyclerView有关的最重要的类
Adapter:适配器,绑定数据集
ViewHolder:根据当前的数据保存视图
LayoutManager:布局管理器。决定item如何摆放
ItemDecoration:勉强理解为item装饰器,可以美化item
ItemAnimator:动画,当一个item被增加,删除或者重新摆放时,会有动画效果。
谷歌使用了RecyclerView的内部类Adapter代替了传统的Adapter,所以在RecyclerView中,你不会见到类似SimpleCursorAdapter, ArrayAdapter这样的适配器。
然而不幸的是谷歌并没有提供RecyclerView.Adapter的默认实现类,它是一个抽象类,所以我们必须去实现三个方法。
public VH onCreateViewHolder(ViewGroup parent, int viewType)
public void onBindViewHolder(VH holder, int position)
public int getItemCount()
VH是一个继承自ViewHolder的泛型,在子类中必须提供具体的类型。最基本的适配器写法如下
public void onDraw(Canvas c, RecyclerView parent)
public void onDrawOver(Canvas c, RecyclerView parent)
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent)
在onDraw中绘制的内容可能会被item的内容遮挡,但是你在onDrawOver中绘制的内容会被绘制在item上方。我们可以使用偏移量对item进行简单分割,但是如果你想显示一条分割线,你就不得不去使用onDrawOver方法去显式的绘制一条分隔线。
布局管理器会在测量阶段调用getItemOffset方法,它与一个Rect类型的参数,outRect 参数看上去有点怪怪的,那么为什么不用一个返回值代替它呢,既然谷歌这样做了,必然是有意义的。因为这样可以让所有item去复用一个Rect对象因此节约了资源,这样做不一定是最好的,但是的确可以有效节约资源。
有一点要值得注意的是,onDraw()/onDrawOver()方法并不会为每个item调用,它只会被调用一次去绘制所有item的装饰内容。因此我们必须在该方法中遍历所有item进行绘制。
上篇文章简单提供了一个DividerItemDecoration的源码,当然我们可以通过继承ItemDecoration 去实现更加丰富的内容。
一个item被添加到数据集中
一个item从数据集中被移除
一项在界面中位置被移动了
幸运的是,在v7兼容包中提供了一个默认的实现类叫做DefaultItemAnimator,如果我们不设置,默认就会适应该类。
如果想让动画生效,很明显android必须知道数据改变了。在早期的适配器中,我们需要调用notifyDataSetChanged方法通知android数据集改变了。但是现在不再适用了,这个方法会重绘所有可见item但是不会触发任何动画,我们必须调用类似以下的方法才能触发动画。
public final void notifyItemInserted(int position)
public final void notifyItemRemoved(int position)
tools属性会渲染当前布局,当我们切换到可视化编辑器的时候可以看到效果,当然也可以不写,只是看不到效果罢了。
我们可以看到,并没有使用一些特别的属性,实际上RecyclerView的属性都是来自其父类ViewGroup。在RecyclerView中有一个方法用到了AttributeSet,这个方法就是generateLayoutParams,但是在内部它也并没有怎么对属性进行操作。
而在Activity中使用它也是很简单的
总结为以下几步
获得RecyclerView引用
创建布局管理器并添加到RecyclerView中
创建适配器并添加到RecyclerView中
创建0到多个item装饰器ItemDecoration,前提是有必要的话
创建ItemAnimator,如果有必要的话
创建0到多个监听器并增加到RecyclerView中
基本源码同上篇文章,源码下载地址http://download.csdn.net/detail/sbsujjbcy/8489667
本篇文章参考了http://www.grokkingandroid.com/first-glance-androids-recyclerview/
在RecyclerView的API中,有这样一句话
A flexible view for providing a limited window into a large data set.
大致意思就是:当有大量的数据显示在一个有限大小的窗口上时,RecyclerView就是解决这种情况的一个灵活的View。
从以上描述可以看出RecyclerView的使用场景。如果我们有大量的同一类型的数据要显示在屏幕上,而此时很有可能整个屏幕无法完全显示所有的数据,这时候RecyclerView就是一个合适的选择。当用户上下滚动屏幕的时候,item的循环重复利用也在同时进行,当一个新的item进入可视范围,必然有一个旧的item移出可视范围,而这个被移出的item也就被循环重用。那么循环重用item有什么作用呢,其实他是很有用的一种方法,因为它节省了CPU资源和内存。
或许你会说我们用ListView用了很长的时间了,RecyclerView与我们以前的方式有什么特别的地方呢,从前,我们使用listview的时候,显示,循环重用以及其它的一些东西都有一定程度上的耦合性,现在RecyclerView则提供了一种更加灵活的方式。
谷歌现在使用的这种方法,它不在乎RecyclerView所看到的东西,也不在乎元素是否显示在正确的地方,更不在乎每个元素是如何分隔的。RecyclerView做的事仅仅是是回收。因此得名RecyclerView。
下面是几个和RecyclerView有关的最重要的类
Adapter:适配器,绑定数据集
ViewHolder:根据当前的数据保存视图
LayoutManager:布局管理器。决定item如何摆放
ItemDecoration:勉强理解为item装饰器,可以美化item
ItemAnimator:动画,当一个item被增加,删除或者重新摆放时,会有动画效果。
ViewHolder
安卓官方已经推荐使用ViewHolder模式有很长一段时间了,因为它能在一定程度上大大提高效率,界面流畅性增加。RecyclerView的适配器是一个内部类,我们通过继承它来扩展我们的子类,就像这样。public final static class ListItemViewHolder extends RecyclerView.ViewHolder { TextView title;//item界面上的一个元素 TextView description;//item界面上的一个元素 //当然可以继续增加这些元素 public ListItemViewHolder(View itemView) { super(itemView); //关联引用 title= (TextView) itemView.findViewById(R.id.title); description= (TextView) itemView.findViewById(R.id.description); } }
RecyclerView.Adapter
适配器完成两个主要功能:负责建立基础数据集和单个item布局之间的联系。适配器是Android的一个重要部分之一。它被用在许多地方,比如ListView, AutoCompleteTextView, Spinner都用到了适配器。谷歌使用了RecyclerView的内部类Adapter代替了传统的Adapter,所以在RecyclerView中,你不会见到类似SimpleCursorAdapter, ArrayAdapter这样的适配器。
然而不幸的是谷歌并没有提供RecyclerView.Adapter的默认实现类,它是一个抽象类,所以我们必须去实现三个方法。
public VH onCreateViewHolder(ViewGroup parent, int viewType)
public void onBindViewHolder(VH holder, int position)
public int getItemCount()
VH是一个继承自ViewHolder的泛型,在子类中必须提供具体的类型。最基本的适配器写法如下
public class RecyclerViewAdapter extends RecyclerView.Adapter <RecyclerViewAdapter.ItemViewHolder> { private List<DemoModel> items; RecyclerViewAdapter(List<DemoModel> modelData) { if (modelData == null) { throw new IllegalArgumentException( "modelData must not be null"); } this.items = modelData; } @Override public ItemViewHolder onCreateViewHolder( ViewGroup viewGroup, int viewType) { View itemView = LayoutInflater. from(viewGroup.getContext()). inflate(R.layout.item,viewGroup,false); return new ItemViewHolder(itemView); } @Override public void onBindViewHolder( ItemViewHolder viewHolder, int position) { DemoModel model = items.get(position); viewHolder.title.setText(model.getTitle()); viewHolder.description.setText(model.getDescription()); } @Override public int getItemCount() { return items.size(); } public final static class ItemViewHolder extends RecyclerView.ViewHolder { // ... shown above in the ViewHolder section } }
RecyclerView.LayoutManager
布局管理器是RecyclerView最有意思的一个地方,它负责对所有子item进行布局,在最新的v7兼容库中,它有三个实现类,分别是LinearLayoutManager(线性布局),GridLayoutManager(a网格布局),StaggeredGridLayoutManager(流式布局),默认情况下,如果我们不设置布局管理器,将使用线性布局。我们可以通过继承该类实现自己的布局管理器,由我们自己决定如何摆放item的内容,然而,当你去看上面的三个实现类的代码时,你会发现这是多么不容易的一件事。。。代码好长。。。真的!布局管理器的具体使用方法将再开一篇博客,这里先介绍一下线性布局管理器的简单使用。代码如下//实例化对象 LinearLayoutManager layoutManager = new LinearLayoutManager(context); //设置布局方向为竖直 layoutManager.setOrientation(LinearLayoutManager.VERTICAL); //滚动到那一项 layoutManager.scrollToPosition(currPos); //设置布局管理器 recyclerView.setLayoutManager(layoutManager);
RecyclerView.ItemDecoration
姑且我叫它为item装饰器,使用ItemDecoration我们可以给item增加偏移量,增加item分割线,高亮等等。我们可以能增加很多个ItemDecoration,RecyclerView 会依次遍历所有的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中绘制的内容可能会被item的内容遮挡,但是你在onDrawOver中绘制的内容会被绘制在item上方。我们可以使用偏移量对item进行简单分割,但是如果你想显示一条分割线,你就不得不去使用onDrawOver方法去显式的绘制一条分隔线。
布局管理器会在测量阶段调用getItemOffset方法,它与一个Rect类型的参数,outRect 参数看上去有点怪怪的,那么为什么不用一个返回值代替它呢,既然谷歌这样做了,必然是有意义的。因为这样可以让所有item去复用一个Rect对象因此节约了资源,这样做不一定是最好的,但是的确可以有效节约资源。
有一点要值得注意的是,onDraw()/onDrawOver()方法并不会为每个item调用,它只会被调用一次去绘制所有item的装饰内容。因此我们必须在该方法中遍历所有item进行绘制。
上篇文章简单提供了一个DividerItemDecoration的源码,当然我们可以通过继承ItemDecoration 去实现更加丰富的内容。
RecyclerView.ItemAnimator
ItemAnimator类主要是处理动画效果,以下三种情况,会触发该动画。一个item被添加到数据集中
一个item从数据集中被移除
一项在界面中位置被移动了
幸运的是,在v7兼容包中提供了一个默认的实现类叫做DefaultItemAnimator,如果我们不设置,默认就会适应该类。
如果想让动画生效,很明显android必须知道数据改变了。在早期的适配器中,我们需要调用notifyDataSetChanged方法通知android数据集改变了。但是现在不再适用了,这个方法会重绘所有可见item但是不会触发任何动画,我们必须调用类似以下的方法才能触发动画。
public final void notifyItemInserted(int position)
public final void notifyItemRemoved(int position)
Listeners
监听器,RecyclerView中不再有OnItemClickListener和OnItemLongClickListener监听器,但是我们可以使用OnItemTouchListener再配合手势去识别这些事件,这意味着我们需要编写更多的代码去实现同样的效果。综上所述
在布局文件中使用,代码如下<android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" tools:listitem="@layout/item_demo_01" />
tools属性会渲染当前布局,当我们切换到可视化编辑器的时候可以看到效果,当然也可以不写,只是看不到效果罢了。
我们可以看到,并没有使用一些特别的属性,实际上RecyclerView的属性都是来自其父类ViewGroup。在RecyclerView中有一个方法用到了AttributeSet,这个方法就是generateLayoutParams,但是在内部它也并没有怎么对属性进行操作。
@Override public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { if (mLayout == null) { throw new IllegalStateException("RecyclerView has no LayoutManager"); } return mLayout.generateLayoutParams(getContext(), attrs); }
而在Activity中使用它也是很简单的
//获得控件引用 recyclerView = (RecyclerView) findViewById(R.id.recyclerView); //实例化布局管理器并设置布局管理器,滚动到顶部 LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); layoutManager.scrollToPosition(0); recyclerView.setLayoutManager(layoutManager); // 当item大小一样时有利于优化,具体怎么个优化法我也不知道。。 recyclerView.setHasFixedSize(true); // 绑定适配器并提供数据集 List<DemoModel> items = new ArratList<DemoModel>(); //......这里进行数据的初始化工作 adapter = new RecyclerViewDemoAdapter(items); recyclerView.setAdapter(adapter); //使用装饰器,该类的源码在上一篇文章中有提供 RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST); //注意这里是add而不是set,说明可以添加多个 recyclerView.addItemDecoration(itemDecoration); // 下面这句话可以不写,因为默认就是使用该类; // 当我们自定义了动画,才有必要去设置 recyclerView.setItemAnimator(new DefaultItemAnimator()); // 设置监听器,需要配合手势 //recyclerView.addOnItemTouchListener(this);
总结为以下几步
获得RecyclerView引用
创建布局管理器并添加到RecyclerView中
创建适配器并添加到RecyclerView中
创建0到多个item装饰器ItemDecoration,前提是有必要的话
创建ItemAnimator,如果有必要的话
创建0到多个监听器并增加到RecyclerView中
基本源码同上篇文章,源码下载地址http://download.csdn.net/detail/sbsujjbcy/8489667
本篇文章参考了http://www.grokkingandroid.com/first-glance-androids-recyclerview/
相关文章推荐
- android v7兼容包RecyclerView的使用(一)
- android v7兼容包RecyclerView的使用(三)——布局管理器的使用
- android v7兼容包RecyclerView的使用(四)——点击事件的不同方式处理
- android v7兼容包RecyclerView的使用(四)——点击事件的不同方式处理
- android v7兼容包RecyclerView的使用
- Android 5.0 RecyclerView 使用
- 如何使用Android最新的RecyclerView取代ListView?
- [Android]使用RecyclerView替代ListView(三)
- Android开发--RecyclerView使用,看AndroidL新特性
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 的简单使用
- Android使用RecyclerView替代ListView(一)
- Android RecyclerView 的简单使用
- Android RecyclerView 使用完全解析 体验艺术般的控件
- ANDROID L——RecyclerView,CardView导入和使用(Demo)
- Android RecyclerView 使用完全解析 体验艺术般的控件
- [Android]使用RecyclerView替代ListView(一)
- ANDROID L——RecyclerView,CardView导入和使用(Demo)
- Android 5.0材料设计 RecyclerView的使用
- Android RecyclerView 使用完全解析 体验艺术般的控件