RecyclerView是在support.v7中添加的,目标是为任何基于适配器的视图提供相似的渲染方式。它被作为ListView和GridView控件的继承者,主要是在使用Adapter时,更加高效,那么今天我们就来看看RecyclerView的说明以及使用。
一、官网说明
RecyclerView是一个灵活的View,提供了在一个有限的窗口上展示很大的数据集合。
专业术语:
(1).Adapter : RecyclerView.Adapter的子类,负责提供View中item的数据集合。
(2).Position : 一个数据项在Adapter中的位置。
(3).Index: 附加子view被用于调用getChildAt(int)的索引。
(4).Binding: 子view中显示数据在Adapter中的合适位置的准备过程。
(5).Recycle (view): 一个预先View,被用来在特别的Adapter位置中显示数据,可能位于缓存中为后面再次重用显示相同类型的数据。这极大程度上提高了性能,跳过原始布局和构建。
(6).Scrap (view): 一个子View在布局时进入暂时分离状态。Scrap views可能被重用,当没有完全从父RecyclerView分离时,如果没有重绑要求那么不修改,或者如果view是脏数据,那么通过adapter 修改。
(7).Dirty (view): 一个子view在显示之前,必须要重新绑定在Adapter中。
二、概念
使用RecyclerView是,需要先认识几个类,RecyclerView.Adapter ,LayoutManager,ItemAnimator 。
1. RecyclerView.Adapter。
它与之前使用的适配器类似,但也稍有不同,例如它需要使用ViewHolder。作用是用来将数据和布局item进行绑定。
2.LayoutManager。
布局管理器,这个类决定视图被放在画面中哪个位置,并且,它也可以管理滚动和循环利用。设置每一项view在RecyclerView中的位置布局以及控件item view的显示或者隐藏.当重用或者回收一个view的时候,LayoutManger都会向Adapter来请求新的数据来进行替换原来数据的内容。这种回收重用的机制可以提供性能,避免创建很多的view或者是频繁的调用findViewById方法。这种机制和ListView还是很相似的。RecyclerView提供了三种内置的LayoutManager:
(1).LinearLayoutManager:线性布局,横向或者纵向滑动列表
(2). GridLayoutManager:表格布局
(3). StaggeredGridLayoutManager:流式布局
当然除了上面的三种内部布局之外,我们还可以自定义这个LayoutManager类。
3.ItemAnimator 。
ItemAnimator会根据适配器上收到的通知动画显示视图组的修改。基本上,它会自动显示添加和移除条目动画。负责处理数据添加或者删除时候的动画效果。
三、使用
我使用的Android Studio。
1.创建新的Module。
2. 首先导入RecyclerView的类库,在build.gradle中加入如下代码,
dependencies {
…….
compile 'com.android.support:recyclerview-v7:24.2.1'
}
如果你使用的Eclipse,那么请导入android-support-v7包即可。
3. 在布局文件中,加入 RecyclerView控件,
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="cn.xinxing.recyclerviewtest.MainActivity">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rv_id"
/>
</RelativeLayout>
4.创建一个Adapter,该继承自RecyclerView.Adapter,
public class StudensListAdapter extends RecyclerView.Adapter<StudensListAdapter.ViewHolder> {
private List<String> mDatas;
private LayoutInflater mLayoutInflater;
public StudensListAdapter(Context context, List<String> mDatas) {
this.mDatas = mDatas;
mLayoutInflater = LayoutInflater.from(context);
}
/**
* 创建ViewHolder ,ViewHolder的个数是可见的item数量
*
* @param parent
* @param viewType
* @return
*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ViewHolder viewHolder = new ViewHolder(mLayoutInflater.inflate(R.layout.adapter_item_student, parent, false));
return viewHolder;
}
/**
* 加载数据
*
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.tv.setText(mDatas.get(position));
}
/**
* view的个数
*
* @return
*/
@Override
public int getItemCount() {
return mDatas.size();
}
/**
* 创建ViewHolder对象
*/
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView tv;
public ViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.tv_id);
}
}
}
(1).创建一个ViewHolder类,继承自RecyclerView.ViewHolder,在ViewHolder方法中,添加绑定控件;
(2).重新RecyclerView.Adapter的三个方法,getItemCount(),onCreateViewHolder(),onBindViewHolder()。
5. Activity中添加代码,
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private StudensListAdapter mStudensListAdapter;
private List<String> mDatas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.rv_id);
initLists();
initAdapter();
}
private void initAdapter() {
mStudensListAdapter = new StudensListAdapter(this, mDatas);
mRecyclerView.setAdapter(mStudensListAdapter);
//设置布局管理器
RecyclerView.LayoutManager layoutManage = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManage);
//设置动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
}
private void initLists() {
mDatas=new ArrayList<>();
mDatas.add("zhangsan");
mDatas.add("lisi");
mDatas.add("wangwu");
mDatas.add("kk");
mDatas.add("lq");
}
}
运行后的效果图如下,
PS: 如果想要添加分割线,
mRecyclerView.addItemDecoration();
但是,目前官方没有提供默认的实现,需要自己继承ItemDecoration。
private void initAdapter() {
mStudensListAdapter = new StudensListAdapter(this, mDatas);
mRecyclerView.setAdapter(mStudensListAdapter);
//设置布局管理器
RecyclerView.LayoutManager layoutManage = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManage);
//设置分割线
mRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));
//设置动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
}
运行后的效果如下所示:
此处提供几个已经定义好的类,(是从鸿洋的博客中直接拿过来的,)DividerItemDecoration.java 和DividerGridItemDecoration.java。
如果想要出现类似GridView的效果,那么只需要修改布局管理器为GridLayoutManager以及分割线即可,
private void initAdapter() {
mStudensListAdapter = new StudensListAdapter(this, mDatas);
mRecyclerView.setAdapter(mStudensListAdapter);
//设置布局管理器
RecyclerView.LayoutManager layoutManager=new GridLayoutManager(this,3);
mRecyclerView.setLayoutManager(layoutManager);
//设置分割线
mRecyclerView.addItemDecoration(new DividerGridItemDecoration(this));
//设置动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
}
运行后的效果如下,
是不是很简单呢!如果要实现瀑布流效果呢!需要布局管理器为StaggeredGridLayoutManager,请看代码,
private void initAdapter() {
mStudensListAdapter = new StudensListAdapter(this, mDatas);
mRecyclerView.setAdapter(mStudensListAdapter);
//设置布局管理器
RecyclerView.LayoutManager layoutManager=new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
//设置分割线
SpacesItemDecoration spacesItemDecoration=new SpacesItemDecoration(10);
mRecyclerView.addItemDecoration(spacesItemDecoration);
//设置动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
}
为此,我们还需要自己实现一个分割线,
public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
private int space;
public SpacesItemDecoration(int space) {
this.space=space;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.left=space;
outRect.right=space;
outRect.bottom=space;
if(parent.getChildAdapterPosition(view)==0){
outRect.top=space;
}
}
}
并且我们还需要设置item的高度为一个随机数,
private void getRandomHeight(List<String> lists){//得到随机item的高度
heights = new ArrayList<>();
for (int i = 0; i < lists.size(); i++) {
heights.add((int)(100+Math.random()*400));
}
}
然后,我们在onBindViewHolder中调用,
/**
* 加载数据
*
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();//得到item的LayoutParams布局参数
params.height = heights.get(position);//把随机的高度赋予item布局
holder.itemView.setLayoutParams(params);//把params设置给item布局
holder.tv.setText(mDatas.get(position));
}
运行后的效果如下,
使用RecyclerView在这三种效果之间切换是不是很简单呢!!使用RecyclerView,可以高度定制!
PS:
1.更新RecyclerView的Item时,可以只更新当前Item,只需调用相应代码即可,
//添加
notifyItemInserted(position);
//删除
notifyItemRemoved(position);
2.
RecyclerView没有提供监听方法,需要自己去实现,首先在Adapter中定义监听方法,
...
public OnItemClickListener mOnItemClickListener;
public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
this.mOnItemClickListener = mOnItemClickListener;
}
public void onBindViewHolder(final MyViewHolder holder, final int position)
{
holder.tv.setText(mDatas.get(position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mOnItemClickListener != null) {
int pos = holder.getLayoutPosition();
mOnItemClickListener.OnItemClick(holder.itemView, pos);
}
}
});
}
public interface OnItemClickListener {
public void OnItemClick(View view, int position);
}
...
在Activity中注册该监听方法,
mStudensListAdapter.setOnItemClickListener(new StudensListAdapter.OnItemClickListener() {
@Override
public void OnItemClick(View view, int position) {
Toast.makeText(MainActivity.this, position + " click",
Toast.LENGTH_SHORT).show();
}
});
四、总结。
相比ListView只需设置Adapter而言,RecyclerView的使用看起来似乎要复杂一些。但是它的使用更加灵活。
(1).强制使用ViewHolder;
(2).需要自己去实现监听方法,例如onItemClickListener方法;
(3).需要自己去实现分割线类;
(4).可以自定义的动画效果。
总体来说,使用RecyclerView更加方便快捷的实现这种Item列表效果!
更加详细的,请参考 Android RecyclerView 使用完全解析 体验艺术般的控件 。