Android RecyclerView详解

    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 使用完全解析 体验艺术般的控件


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值