android开发之recycleView的使用

作者: zzj丶 | 来源:发表于2017-02-16 21:25 被阅读261次

    一、recycleView的使用场景

    1、多种样式的列表
    2、宫格和列表同时存在
    3、分类列表比如通讯录城市列表等

    二、基本使用

    在布局文件中声明
    在Activity中使用
    Adapter的创建
    添加单击事件
    Item动画
    更新数据

    1、在布局文件中声明
    
    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
     
    
    2、在Activity中使用
    
    复制代码
    // 1,找到这个View
    mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
    // 2,设置布局管理LayoutManager
    mLayoutManager = new LinearLayoutManager(this);
    mRecyclerView.setLayoutManager(mLayoutManager);
    // 3,(可选)如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
    mRecyclerView.setHasFixedSize(true);
    // 4,设置Adapter
    mRecyclerView.setAdapter(new MyAdapter());
    复制代码
     
    
    目前SDK中提供了三种自带的LayoutManager:
    
    LinearLayoutManager
    
    GridLayoutManager
    
    StaggeredGridLayoutManager
    
    LinearLayoutManager
    
    mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
    GridLayoutManager
    
    mLayoutManager = new GridLayoutManager(context,columNum);
    mRecyclerView.setLayoutManager(mLayoutManager);
    注:在Grid布局中也可以设置列表的Orientation属性,来实现横向和纵向的Grid布局。
    
    StaggeredGridLayoutManager
    
    瀑布流就使用StaggeredGridLayoutManager吧,具体使用方法见http://blog.csdn.net/duanymin/article/details/44979355
    
     
    
    3、Adapter的创建
    
    复制代码
     1 public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
     2     public String[] datas = null;
     3     public MyAdapter(String[] datas) {
     4         this.datas = datas;
     5     }
     6     //创建新View,被LayoutManager所调用
     7     @Override
     8     public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
     9         View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item,viewGroup,false);
    10         ViewHolder vh = new ViewHolder(view);
    11         return vh;
    12     }
    13     //将数据与界面进行绑定的操作
    14     @Override
    15     public void onBindViewHolder(ViewHolder viewHolder, int position) {
    16         viewHolder.mTextView.setText(datas[position]);
    17     }
    18     //获取数据的数量
    19     @Override
    20     public int getItemCount() {
    21         return datas.length;
    22     }
    23     //自定义的ViewHolder,持有每个Item的的所有界面元素
    24     public static class ViewHolder extends RecyclerView.ViewHolder {
    25         public TextView mTextView;
    26         public ViewHolder(View view){
    27         super(view);
    28             mTextView = (TextView) view.findViewById(R.id.text);
    29         }
    30     }
    31 }
    复制代码
     
    
    4、添加单击事件
    
    复制代码
    // 1 定义接口
    public static interface OnRecyclerViewItemClickListener {
        void onItemClick(View view , DataModel data);
    }
    
    // 2 添加接口和设置接口的方法
    private OnRecyclerViewItemClickListener mOnItemClickListener = null;
    public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
        this.mOnItemClickListener = listener;
    }
    
    // 3 在Adapter实现OnClickListener方法
    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener{
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {
            View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
            ViewHolder vh = new ViewHolder(view);
            //将创建的View注册点击事件
            view.setOnClickListener(this);
            return vh;
        }
        @Override
        public void onBindViewHolder(ViewHolder viewHolder, final int i) {
            viewHolder.mTextView.setText(datas.get(i).title);
            //将数据保存在itemView的Tag中,以便点击时进行获取
            viewHolder.itemView.setTag(datas.get(i));
        }
        ...
        @Override
        public void onClick(View v) {
            if (mOnItemClickListener != null) {
                //注意这里使用getTag方法获取数据
    
            }
        ...
    }
    复制代码
    在Activity中
    
    复制代码
    mAdapter = new MyAdapter(getDummyDatas());
    mRecyclerView.setAdapter(mAdapter);
    mAdapter.setOnItemClickListener(new MyAdapter.OnRecyclerViewItemClickListener() {
        @Override
        public void onItemClick(View view, DataModel data) {
            //DO your fucking bussiness here!
        }
    });
    复制代码
     
    
    5、Item动画
    
    // 设置item动画
    mRecyclerView.setItemAnimator(new DefaultItemAnimator());
    如果要自定义动画效果需要继承ItemAnimator
    
    GitHub上的动画效果:RecyclerViewItemAnimators
    
     
    
    6、更新数据
    
    这里更新数据集不是用adapter.notifyDataSetChanged()而是 notifyItemInserted(position)与notifyItemRemoved(position) 否则没有动画效果。 
    
    为adapter中添加两个方法:
    
    复制代码
    public void addData(int position) {
        mDatas.add(position, "Insert One");
        notifyItemInserted(position);
    }
    
    public void removeData(int position) {
        mDatas.remove(position);
        notifyItemRemoved(position);
    }
    

    三、复杂布局的实现逻辑

    1、RecycleView的关键成员

      A、Type:类型 通过getItemViewType(position)获取
      B、Holder(熟悉ListView的都知道)
            1、holder在recycleView中保存view的单位
            2、记录recycleview中的基本信息
      C、RecycleView.Recycler(保存了一些缓存机制)
             1、Recycleview中被缓存的holder
             2、多个RecycleView共用一个RecycleredPool(缓存池)
             3、配置缓存size
    

    2、getItemViewType

     a、ItemType保存在Holder中
     B、Holder根据position被缓存在cache中
     RecycleView之所以流畅,就是当我们需要复用的时候系统会在cache中拿holder,进而实现使用流畅。
     C、遍历缓存中的holder,如果Type一致就返回。  
    

    3、多布局的实现

     A、复写getItemViewType方法
     B、需要处理getItemCount方法
     C、按照获取的Type处理onCreateViewHolder和OnBinderViewHolder。
    

    4、数据的处理

     A、把多个数据类型都包装进一个Object(不利于查找)
     B、封装RecycleView.Adapter,把一些不同的item当做header添加进来
    

    5、多布局类型运行流程

    滚动布局——》通过getItemViewType获取Type类型——》根据类型寻找holder——》如果holder为null执行adapter.createrHolder,否则执行adapter.bindViewHolder.

    四、通过LinearLayoutManager实现多布局代码:

     recyclerView = (RecyclerView) findViewById(R.id.recycleview);
            recyclerView.setLayoutManager(new LinearLayoutManager(this,
                    LinearLayoutManager.VERTICAL,false));
            adapter = new MyRecyclerViewAdapter(this);
            recyclerView.setAdapter(adapter);
            initData();
    

    /**
    * 模拟数据
    /
    private void initData(){
    List<DataBean> dataBeanList = new ArrayList<>();
    for(int i=0;i<20;i++){
    int type = (int) ((Math.random()
    3)+1);
    DataBean dataBean = new DataBean();
    dataBean.titelColor = typeColors[type-1];
    dataBean.type = type;
    dataBean.contentColor = typeColors[(type+1)%3];
    dataBean.content = "content"+i;
    dataBean.name = "name"+i;
    dataBeanList.add(dataBean);
    }
    adapter.addData(dataBeanList);
    }

    }

    多布局就是不同的Viewholder加载渲染不同的布局,通过Type进行区分。
    布局一和所对应的viewHolder、

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:gravity="center_vertical"
        android:layout_height="60dp">
        <ImageView
            android:layout_marginLeft="20dp"
            tools:src="@mipmap/ic_launcher"
            android:id="@+id/title_image"
            android:layout_width="45dp"
            android:layout_height="45dp" />
    
        <TextView
            android:id="@+id/name_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:text="测试名字"
            android:layout_marginLeft="10dp"
            />
    </LinearLayout>
    
    
    /**
     * 布局一viewholder
     * Created by zzj on 2017/2/16.
     */
    
    public class TypeOneHolder extends TypeAbstractHolder {
        private ImageView titel_image;
        private TextView name_tv;
        public TypeOneHolder(View itemView) {
            super(itemView);
            titel_image = (ImageView) itemView.findViewById(R.id.title_image);
            name_tv = (TextView) itemView.findViewById(R.id.name_tv);
        }
    
        @Override
        public void onBindData(DataBean dataBean) {
            titel_image.setImageResource(dataBean.titelColor);
            name_tv.setText(dataBean.name);
        }
    }
    

    布局二、

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:gravity="center_vertical"
        android:layout_height="60dp">
        <ImageView
            android:layout_marginLeft="20dp"
            tools:src="@mipmap/ic_launcher"
            android:id="@+id/title_image"
            android:layout_width="45dp"
            android:layout_height="45dp" />
    
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            >
            <TextView
                android:id="@+id/name_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                tools:text="测试名字"
                android:layout_marginLeft="10dp"
                />
            <TextView
                android:id="@+id/content_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                tools:text="测试内容"
                android:layout_marginTop="5dp"
                android:layout_marginLeft="10dp"
                />
        </LinearLayout>
    </LinearLayout>
    
    
    /**布局二viewholder
     * Created by zzj on 2017/2/16.
     */
    
    public class TypeTwoHolder extends TypeAbstractHolder {
        private ImageView titel_image;
        private TextView name_tv,content_tv;
        public TypeTwoHolder(View itemView) {
            super(itemView);
            titel_image = (ImageView) itemView.findViewById(R.id.title_image);
            name_tv = (TextView) itemView.findViewById(R.id.name_tv);
            content_tv = (TextView) itemView.findViewById(R.id.content_tv);
    
        }
    
        @Override
        public void onBindData(DataBean dataBean) {
            titel_image.setImageResource(dataBean.titelColor);
            name_tv.setText(dataBean.name);
            content_tv.setText(dataBean.content);
        }
    }
    
    

    布局三、

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:gravity="center_vertical"
        android:layout_height="60dp">
        <ImageView
            android:layout_marginLeft="20dp"
            tools:src="@mipmap/ic_launcher"
            android:id="@+id/title_image"
            android:layout_width="45dp"
            android:layout_height="45dp" />
    
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            >
            <TextView
                android:id="@+id/name_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                tools:text="测试名字"
                android:layout_marginLeft="10dp"
                />
            <TextView
                android:id="@+id/content_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                tools:text="测试内容"
                android:layout_marginTop="5dp"
                android:layout_marginLeft="10dp"
                />
        </LinearLayout>
    
        <ImageView
            android:id="@+id/content_image"
            tools:src="@mipmap/ic_launcher"
            android:layout_width="100dp"
            android:layout_height="40dp"
            android:layout_marginLeft="60dp"
            />
    </LinearLayout>
    
    
    /**布局三viewholder
     * Created by zzj on 2017/2/16.
     */
    
    public class TypeThreeHolder extends TypeAbstractHolder {
        private ImageView titel_image,content_image;
        private TextView name_tv,content_tv;
        public TypeThreeHolder(View itemView) {
            super(itemView);
            titel_image = (ImageView) itemView.findViewById(R.id.title_image);
            name_tv = (TextView) itemView.findViewById(R.id.name_tv);
            content_tv = (TextView) itemView.findViewById(R.id.content_tv);
            content_image = (ImageView) itemView.findViewById(R.id.content_image);
        }
    
        @Override
        public void onBindData(DataBean dataBean) {
            titel_image.setImageResource(dataBean.titelColor);
            name_tv.setText(dataBean.name);
            content_tv.setText(dataBean.content);
            content_image.setImageResource(dataBean.contentColor);
        }
    }
    
    

    ViewHolder的父类

    public abstract class TypeAbstractHolder extends RecyclerView.ViewHolder {
    
        public TypeAbstractHolder(View itemView) {
            super(itemView);
        }
    
        /**
         * 绑定数据
         * @param dataBean
         */
        public abstract void onBindData(DataBean dataBean);
    }
    

    在Adapter中创建绑定ViewHolder

    
          @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            switch (viewType){
                case DataBean.TYPE_ONE:
                    return new TypeOneHolder(inflater.inflate(R.layout.item_recycleview_linear_type_one,parent,false));
                case DataBean.TYPE_TWO:
                    return new TypeTwoHolder(inflater.inflate(R.layout.item_recycleview_linear_type_two,parent,false));
                case DataBean.TYPE_THREE:
                    return new TypeThreeHolder(inflater.inflate(R.layout.item_recycleview_linear_type_three,parent,false));
            }
            return null;
        }
    
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            ((TypeAbstractHolder)holder).onBindData(dataBeanList.get(position));
        }
    
    

    由上而下的多布局就基本创建完成。

    相关文章

      网友评论

        本文标题:android开发之recycleView的使用

        本文链接:https://www.haomeiwen.com/subject/ndghwttx.html