RecyclerView的使用全解

时间:2021-11-13 13:13:54

介绍

RecyclerView与ListView原理是类似的:都是仅仅维护少量的View并且可以展示大量的数据集。RecyclerView用以下两种方式简化了数据的展示和处理:

使用LayoutManager来确定每一个item的排列方式。
为增加和删除项目提供默认的动画效果。
你也可以定义你自己的LayoutManager和添加删除动画,RecyclerView项目结构如下:
RecyclerView的使用全解

Adapter:使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器,作用是将数据与每一个item的界面进行绑定。
LayoutManager:用来确定每一个item如何进行排列摆放,何时展示和隐藏。回收或重用一个View的时候,LayoutManager会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的View和频繁的调用findViewById方法(与ListView原理类似)。

目前SDK中提供了三种自带的LayoutManager:

LinearLayoutManager
GridLayoutManager
StaggeredGridLayoutManager

recyclerView = (RecyclerView) findViewById(R.id.recyclerView);  
LinearLayoutManager layoutManager = new LinearLayoutManager(this );  
//设置布局管理器 
recyclerView.setLayoutManager(layoutManager);  
//设置为垂直布局,这也是默认的 
layoutManager.setOrientation(OrientationHelper. VERTICAL);  
//设置Adapter 
recyclerView.setAdapter( recycleAdapter);  
 //设置分隔线 
recyclerView.addItemDecoration( new DividerGridItemDecoration(this ));  
//设置增加或删除条目的动画 
recyclerView.setItemAnimator( new DefaultItemAnimator());  
    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

①onCreateViewHolder()
这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。直接省去了当初的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。

②onBindViewHolder()
这个方法主要用于适配渲染数据到View中。方法提供给你了一个viewHolder,而不是原来的convertView。

③getItemCount()
这个方法就类似于BaseAdapter的getCount方法了,即总共有多少个条目。

高级控件使用讲解的参考博客

RecyclerView的使用全解

参考博客,点击查看

简单的RecyclerView使用方法

1、添加依赖

 compile 'com.android.support:recyclerview-v7:24.2.1'
    
    
    
  • 1

2. 使用RecyclerView

<android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
   />
    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5

3.创建适配器设置给RecyclerView

View view = inflater.inflate(R.layout.fragment_home, container, false);
        //获取rv控件
        RecyclerView rv = (RecyclerView) view.findViewById(R.id.rv);
        rv.setLayoutManager(new LinearLayoutManager(getContext()));
        //设置Adapter
        MyAdapter adapter = new MyAdapter();
        rv.setAdapter(adapter);
        return view;
    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4.创建适配器

private class MyAdapter extends RecyclerView.Adapter<MyHolder>{
        private final List<String> list;
        public MyAdapter(){
            list =  new ArrayList<String>();
            for (int i = 0; i < 30; i++) {
                list.add("商品记录" + i)}

}
       //OnCreateViewHolder用来给rv创建缓存的

     public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            //参数3:判断条件 true 1.是打气 2.添加到parent
            View view = LayoutInflater.from(getContext()).inflate(R.layout.main_recyclerview_item,parent,false);
            MyHolder holder = new MyHolder(view);
            return holder;
        }
        //给缓存控件设置数据
        public void onBindViewHolder(MyHolder holder, int position) {

            String item = list.get(position);
            holder.textView.setText(item);
            holder.icon.setImageResource(R.drawable.ic_default);
        }
        //获取记录数

  public int getItemCount() {
            return list.size();
      }

    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

5.创建HolderView

public class MyHolder extends RecyclerView.ViewHolder {
    public ImageView icon;
    public TextView textView;
    //实现的方法
    public MyHolder(View itemView) {
        super(itemView);
        icon= (ImageView) itemView.findViewById(R.id.item_iv_icon);
        textView= (TextView) itemView.findViewById(R.id.item_tv_title);
    }
}  
    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

封装RecyclerView通用适配器

好处:1.数量动态 2.类型不限 Map<Integer,View>    
         作用:封装了Adapter编写的冗余代码,提供简洁的基类

    
    
    
  • 1
  • 2
  • 3

思路:不写死空间变量,而采用Map方式。
步骤:先关注比较火的控件库 使用一下,看一下好处 学习下底层源代码 自己动手体会
①封装了BaseHolder

//抽取BaseHolder继承RecyclerView.ViewHolder
public class BaseHolder extends RecyclerView.ViewHolder {
    //不写死控件变量,而采用Map方式
    private HashMap<Integer, View> mViews = new HashMap<>();
    public BaseHolder(View itemView) {
        super(itemView);
    }
    /** *获取控件的方法 */
    public<T> T getView(Integer viewId){
        //根据保存变量的类型 强转为该类型
        View view = mViews.get(viewId);
        if(view==null){
           view= itemView.findViewById(viewId);
            //缓存
            mViews.put(viewId,view);
        }
        return (T)view;
    }
    /** *传入文本控件id和设置的文本值,设置文本 */
    public BaseHolder setText(Integer viewId, String value){
        TextView textView = getView(viewId);
        if (textView != null) {
            textView.setText(value);
        }
        return this;
    }
    /** * 传入图片控件id和资源id,设置图片 */
    public BaseHolder setImageResource(Integer viewId, Integer resId) {
        ImageView imageView = getView(viewId);
        if (imageView != null) {
            imageView.setImageResource(resId);
        }
        return this;
    }
    //...还可以扩展出各种控件。
    //Fluent API 链式api obj.setxxx().setyyy()....
}
    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

②Holder封装好之后,再封装BaseAdapter

封装的时候,部分参数可以选择由外部的构造函数或者set方法
    public class BaseAdapter<T> extends RecyclerView.Adapter<BaseHolder> {
        private List<T> mList = new ArrayList<>();
        private int layoutId;
        public BaseAdapter(int layoutId,List<T> list){
            this.layoutId=layoutId;
            this. mList=list;
        }
        //onCreateViewHolder用来给rv创建缓存
        @Override
        public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
           //参数3 判断条件 true 1.打气 2.添加到paraent
            // false 1.打气 (参考parent的宽度)
            View view =   LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
            BaseHolder holder = new BaseHolder(view);
            return holder;
        }
       //onBindViewHolder给缓存控件设置数据
        @Override
        public void onBindViewHolder(BaseHolder holder, int position) {
            T item = mList.get(position);
            convert(holder,item);
        }
    protected void convert(BaseHolder holder, T item) {
        //什么都没有做
    }
        //获取记录数据
        @Override
        public int getItemCount() {
            return mList.size();
        }
    }
    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

③封装之后,继承实现

/** *1.extends 把父类的代码继承过来。 可以少写很多代码。 *2.因为是全部拿来的代码,所以不是所有的代码都适合当前。对于不适合当前的代码(方法) * 我们可选择@Override 覆盖|重写 */
public class MyHomeAdapter extends BaseAdapter<String> {
    public MyHomeAdapter(List<String> list) {
        super(R.layout.main_recyclerview_item, list);
    }
    @Override
    protected void convert(BaseHolder holder, String item) {
        holder.setText(R.id.item_tv_title,item).setImageResource(R.id.image,R.drawable.ic_default);
    }
}
    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

④封装之后,代码实现

public class HomeFragment extends Fragment {
    private List<String> list;
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_home, container, false);
        //获取rv控件
        RecyclerView rv = (RecyclerView) view.findViewById(R.id.rv); b
        rv.setLayoutManager(new LinearLayoutManager(getContext()));
        initData();
        //设置Adapter
        MyHomeAdapter adapter = new MyHomeAdapter(list);
        rv.setAdapter(adapter);
        return view;
    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

案例1

依赖
布局文件activity_recycler_view.xml:

<?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.support.v7.widget.RecyclerView  android:id="@+id/id_recyclerview" android:divider="#FFB900" android:dividerHeight="1dp" android:layout_width="match_parent" android:layout_height="match_parent"/>

</RelativeLayout>
    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

让我们来看看变化最大的Adaper:

class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder> {
    private List<String> mList;
    private Context mContext;;
    public HomeAdapter(Context mContext,List<String>mList){
        this.mContext=mContext;
        this.mList=mList;
    }

    public void removeData(int position) {
        mList.remove(position);
        notifyItemRemoved(position);
    }
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        MyViewHolder holder = new MyViewHolder(LayoutInflater.from(
                mContext).inflate(R.layout.item_recycler, parent,
                false));
        return holder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position)
    {
        holder.tv.setText(mList.get(position));
    }

    @Override
    public int getItemCount()
    {
        return mList.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder {

        TextView tv;
        public MyViewHolder(View view)
        {
            super(view);
            tv = (TextView) view.findViewById(R.id.tv_item);
        }
    }
}
    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

最大的改进就是对ViewHolder进行了封装定义,不用自己去自定义了,另外Adaper继承RecyclerView.Adapter,在onCreateViewHolder加载条目布局,在onBindViewHolder中将视图与数据进行绑定。
布局文件item_recycler.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="@android:color/white" android:layout_height="wrap_content" >

    <TextView  android:id="@+id/tv_item" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="moon" />
</FrameLayout>
    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

RecyclerView的使用全解

高级进阶—分割线

                                            <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/production/markdown_views-ea0013b516.css">
                                </div>