RecyclerView浅析

来源:互联网 发布:夏天手工坊淘宝网 编辑:程序博客网 时间:2024/06/11 09:07

RecyclerView是Android5.0新加入的用于替代ListView的UI控件,该控件与适配器Adapter、数据源DataSet的关系如下图所示:


这里写图片描述


RecyclerView的特性

相比于ListView,RecyclerView多了一个LayoutManager,Adapter也有所不同,下面将RecyclerView的新特性罗列如下:

  • 必须指定Adapter和LayoutManager; 
    • 1、需要继承类RecyclerView.Adapter,重写下列方法: 
      • onCreateViewHolder(ViewGroup parent, int viewType);
      • onBindViewHolder(ViewHolder holder, int position);
      • getItemCount();
    • 2、三种内置的LayoutManager 
      • LinearLayoutManager;
      • GridLayoutManager;
      • StaggeredGridLayoutManager;
  • 必须使用ViewHolder模式,以便复用每一个Item;
  • 简化了大量数据的显示和处理; 
    • 1、提供了LayoutManager,用于定位Item Views,用于决定何时重用不再可见的Item Views;
    • 2、提供了默认的动画,用于Items的添加和删除等操作;
  • 可以自定义LayoutManager和动画; 
    • 1、继承类RecyclerView.LayoutManager;
    • 2、继承类RecyclerView.ItemAnimator,重写方法RecyclerView.setItemAnimator();

在Eclipse中配置并使用RecyclerView


在Android官方文档中仅介绍了如何在Android Studio使用RecyclerView,并没有介绍如何在Eclipse中使用,其具体配置方法与同样是在Android5.0版本中引入的系统控件CardView相仿,具体步骤请参阅我的博文《在Eclipse中配置并使用UI控件CardView》。


XML布局

整体布局

<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/recycler_view"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:scrollbars="vertical" ></android.support.v7.widget.RecyclerView>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意:RecyclerView需使用全限定类名。


每个Item的布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:padding="8dp" >    <TextView        android:id="@+id/textview_1"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1"        android:textColor="@android:color/holo_green_dark"        android:textSize="21sp" />    <TextView        android:id="@+id/textview_2"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1"        android:textColor="@android:color/holo_orange_light"        android:textSize="15sp" /></LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

每个Item纵向布置了两个TextView。


定义DataSet

为了给每个Item装入数据,应定义一个类存放相应数据:

package com.test.recyclerview_test2;public class ItemObject {    private String mText_1;    public String getText_1() {        return mText_1;    }    public ItemObject(String text_1, String text_2) {        super();        mText_1 = text_1;        mText_2 = text_2;    }    public ItemObject() {        super();    }    public void setText_1(String text_1) {        mText_1 = text_1;    }    public String getText_2() {        return mText_2;    }    public void setText_2(String text_2) {        mText_2 = text_2;    }    private String mText_2;}
  • 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
  • 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

定义Adapter

继承RecyclerView.Adapter,并重写该类中的3个方法;由于RecyclerView要求必须定义ViewHolder,故还需要在定义的Adapter中定义一个继承了RecyclerView.ViewHolder的内部类。具体代码示例如下所示:


//自定义RecyclerView的Adapter,继承于RecyclerView.Adapter<MyViewHolder>public class CustomRecyclerViewAdapter extends        Adapter<CustomRecyclerViewAdapter.MyViewHolder> {    private ItemObject[] mItemObjects;    private Context mContext;    public CustomRecyclerViewAdapter(ItemObject[] itemObjects, Context context) {        super();        mItemObjects = itemObjects;        mContext = context;    }    public CustomRecyclerViewAdapter() {        super();    }    // 必须定义ViewHolder,继承于RecyclerView.ViewHolder    public static class MyViewHolder extends ViewHolder {        private TextView mTextView_1;        private TextView mTextView_2;        public MyViewHolder(View view) {            super(view);            // TODO Auto-generated constructor stub            mTextView_1 = (TextView) view.findViewById(R.id.textview_1);            mTextView_2 = (TextView) view.findViewById(R.id.textview_2);        }    }    // 返回Item的个数    @Override    public int getItemCount() {        // TODO Auto-generated method stub        return mItemObjects.length;    }    // 绑定ViewHolder与DataSet    @Override    public void onBindViewHolder(MyViewHolder myViewHolder, int position) {        // TODO Auto-generated method stub        myViewHolder.mTextView_1.setText(mItemObjects[position].getText_1());        myViewHolder.mTextView_2.setText(mItemObjects[position].getText_2());    }    // 创建ViewHolder,绑定ViewHolder与Item的XML布局文件    @Override    public MyViewHolder onCreateViewHolder(ViewGroup arg0, int arg1) {        // TODO Auto-generated method stub        View _view = LayoutInflater.from(mContext).inflate(R.layout.item, arg0,                false);        MyViewHolder _myViewHolder = new MyViewHolder(_view);        return _myViewHolder;    }}
  • 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
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 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
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

activity逻辑实现

与ListView相仿,设置RecyclerView为如下步骤:

  1. 设置数据源;
  2. 创建LayoutManager,为RecyclerView设置LayoutManager;
  3. 绑定数据源和Adapter;
  4. 为RecyclerView设置Adapter;

可见,设置RecyclerView比ListView多了第二步,就是设置LayoutManager。


具体示例代码如下:

public class MainActivity extends Activity {    private RecyclerView mRecyclerView;    private LayoutManager mLayoutManager;    private CustomRecyclerViewAdapter mCustomRecyclerViewAdapter;    private ItemObject[] mItemObjects = new ItemObject[100];    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);        // 创建LayoutManager        mLayoutManager = new LinearLayoutManager(this);        // 为RecyclerView设置LayoutManager        mRecyclerView.setLayoutManager(mLayoutManager);        // 设置数据源        for (int i = 0; i < mItemObjects.length; ++i) {            ItemObject _itemObject = new ItemObject();            _itemObject.setText_1("Title Of Item No." + (i + 1));            _itemObject.setText_2("Content Of Item No." + (i + 1));            mItemObjects[i] = _itemObject;        }        // 绑定数据源和Adapter        mCustomRecyclerViewAdapter = new CustomRecyclerViewAdapter(                mItemObjects, this);        // 为RecyclerView设置Adapter        mRecyclerView.setAdapter(mCustomRecyclerViewAdapter);    }}
  • 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
  • 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

demo的实现效果

这里写图片描述这里写图片描述这里写图片描述



在Android Studio中引入RecyclerView

在Android Studio中引入RecyclerView比在Eclipse中简单得多,而且方法有两种:

  • 在Gradle脚本的build.gradle文件中的dependencies中加入compile 'com.android.support:recyclerview-v7:23.+'即可。
  • File–>Project Structure–>Modules(选择用到RecyclerView的module)–>Dependencies选项卡–>点击右上角”+”号引入'com.android.support:recyclerview-v7:23.+'依赖。

RecyclerView的基本用法


要点1:ViewHolder

ViewHolder是RecyclerView的内部类,该内部类要求必须实现,以复用AdapterView中的每一个Item。

public class MyViewHolder extends RecyclerView.ViewHolder{    public TextView mTextView;    public MyViewHolder(View itemView) {        super(itemView);        mTextView = (TextView) itemView.findViewById(android.R.id.text1);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

上述代码中MyViewHolder的构造方法需要传入一个View作为每个Item的布局。


要点2:Adapter

Adapter是RecyclerView的内部类,该内部类需要一个泛型参数ViewHolder,也就是自定义的ViewHolder。


public class MyAdatper extends RecyclerView.Adapter<MyViewHolder> {    //创建数据源    private List<PackageInfo> packageInfos;    public MyAdatper(List<PackageInfo> packageInfos) {        this.packageInfos = packageInfos;    }    //返回泛型参数MyViewHolder对象,MyViewHolder构造方法的参数是AdapterView中的一个Item布局    @Override    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());        return new MyViewHolder(layoutInflater.inflate(android.R.layout.simple_list_item_1, parent, false));    }    //把数据源和ViewHolder联系起来,并设置到每个ItemView中    @Override    public void onBindViewHolder(MyViewHolder holder, int position) {        TextView textView = holder.mTextView;        textView.setText(packageInfos.get(position).packageName);    }    //返回数据源的个数    @Override    public int getItemCount() {        return packageInfos.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
  • 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

要点3:Activity中实现

//从布局中得到RecyclerViewrecyclerView = (RecyclerView) findViewById(R.id.recyclerview);        //得到数据源        packageInfoList = getPackageManager().getInstalledPackages(0);        //创建Adapter对象,绑定数据源        adapter = new MyAdatper(packageInfoList);        //绑定RecyclerView和Adapter        recyclerView.setAdapter(adapter);        //为RecyclerView设置布局方式(参见下面的要点4)        recyclerView.setLayoutManager(new LinearLayoutManager(this));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

实现效果

这里写图片描述


RecyclerView进阶


RecyclerView为Item提供了局部的增删改方法


在ListView中,若有Item中的数据需要增删改,可以调用adapter的notifyDataSetChanged方法,通知ListView刷新数据列表。 
在RecyclerView中也有同样的方法实现同样的效果。除此之外,RecyclerView中的Adapter还提供了刷新增删改的某一项的方法,这些方法可以实现局部操作,节省内存开销。

@Override    public boolean onOptionsItemSelected(MenuItem item) {        int id = item.getItemId();        if (id == R.id.action_add) {            PackageInfo packageInfo = new PackageInfo();            packageInfo.packageName = "com.win16.add";            packageInfoList.add(0, packageInfo);            //点击menu的添加选项时,在列表的第一项添加一条数据            adapter.notifyItemInserted(0);            //将RecyclerView滚动到第一个位置            recyclerView.scrollToPosition(0);        }        else if (id == R.id.action_remove) {            packageInfoList.remove(0);            //点击menu的删除选项时,删除第一项数据            adapter.notifyItemRemoved(0);        }        else if (id == R.id.action_update) {            packageInfoList.get(0).packageName = "com.win16.update";            //点击menu的改变选项时,将第一条数据改为"com.win16.update"            adapter.notifyItemChanged(0);        }        else {            adapter.notifyDataSetChanged();        }        return super.onOptionsItemSelected(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
  • 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

效果展示:


before_addafter_add 
添加一条数据


before_removeafter_remove 
删除一条数据


before_updateafter_update 
修改一条数据


要点4:LayoutManager

LayoutManager是RecyclerView的内部类,该内部类可以灵活定制AdapterView的布局形式:可以是类似于GridView的网格形式——需要new一个GridLayoutManager,可以是普通ListView形式——需要new一个LinearLayoutManager,甚至是瀑布流形式——需要new一个StaggeredGridLayoutManager。


将下面一行:

recyclerView.setLayoutManager(new LinearLayoutManager(this));
  • 1
  • 1

替换为:

recyclerView.setLayoutManager(new GridLayoutManager(this,5, GridLayoutManager.HORIZONTAL,false));
  • 1
  • 1

将布局改变为GridView的样式,指定为5列(行),横向滑动,效果如下:


LayoutManager1 
GridView样式,横向滑动,5行


或替换为GridView瀑布流样式:

recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
  • 1
  • 1

上述代码是GridView瀑布流样式,布局为3列,纵向布置效果如下:


LayoutManager2 
GridView瀑布流样式(每一项是交错的),2列,纵向布置


0 0
原创粉丝点击