0.  前言

随着Android的发展,虽然ListView依旧重要,但RecyclerView确实越来越多的被大家使用。但显然并不能说RecyclerView就一定优于ListView,而是应该根据不同的需求选择最合适的进行使用。本篇将介绍我们为什么要使用RecyclerView,并且它的基本使用方法。

本文原创,转载请注明出处为SEU_Calvin的博客

1.  我们为什么要使用RecyclerView

Google声称你可以把RecyclerView看成是升级版的ListView,为什么ListView没有被遗弃呢?到底RecyclerView强在哪里了呢?

其实如果你只想简单的使用滑动显示这个功能,并且想轻松的使用divider,header,footer或者点击事件这些功能,那么使用ListView是完全没有问题的。RecyclerView除了已经封装好的Item复用机制外,的重点应该放在灵活性上,高度的解耦,这使得RecyclerView能够实现深度的定制化,通过提供的不同LayoutManager,ItemDecoration,ItemAnimator等可以实现很多的效果。

(1)RecyclerView提供的三种布局管理器(LayoutManager),可以无缝衔接ListView、GridView,瀑布流的实现也变得简单,滑动删除和长按交换只需要添加几个类就可以实现。

(2)ListView只有一个notifyDatasetChanged方法,想要做局部刷新还是挺麻烦的,但是在RecyclerView中,有很多适配局部刷新的API。

(3)RecyclerView实现Item增删等动画效果时,因为有了ItemAnimator因此要比ListView简单的多。如果想定制Item之间的间隔,使用ItemDecoration也很方便。

(4)关于点击事件,没有像ListView那样现成的API,但是自己封装起来也不难,而且我们使用ListView时,如果item中有可点击组件,那么点击事件的冲突也是一个问题,而在RecyclerView中则把点击事件的控制权完全的交给开发者。

2.  RecyclerView的简单使用

2.1  Adapter中的实现

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
//…
}

RecyclerView的Adapter需要继承RecyclerView.Adapter<RecyclerAdapter.ViewHolder>

其中有几个比较重要的方法需要实现,分别如下所示:

  @Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
if (TYPE_ITEM == viewType) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
return new ViewHolder(v);
} else {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_footer, viewGroup, false);
return new ViewHolder(view);
}
} @Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
viewHolder.textView.setText(mData.get(i) + i);
} @Override
public int getItemCount() {
return mData.size();
}

其中onCreateViewHolder()将布局转化为View并传递给RecyclerView封装好的ViewHolder,为了展示在RecyclerView中展示两种布局的方式,做了两种区分,即如果是RecyclerView的最后一个条目,则换一种布局展示。这里简单的设置两个布局xml只是背景颜色不同,因此可以返回一样的ViewHolder。而正常情况下可以新建另一个内部类FooterViewHolder extendsRecyclerView.ViewHolder,并在onCreateViewHolder()中进行区分返回。而这个例子中我们返回的ViewHolder是一个内部类。在其中进行控件的初始化。

public class ViewHolder extends RecyclerView.ViewHolder{
public TextView textView;
public ViewHolder(View itemView) {
super(itemView);
textView = (TextView)itemView.findViewById(R.id.id_num);
}
}

在onCreateViewHolder(ViewGroup viewGroup, int viewType)中的第二个参数,就是进行类别区分的,和ListView类似,需要在Adapter内部重写getItemViewType(intposition) 方法,实现哪个位置需要加载哪种布局的逻辑。如下例中,如果是最后一个条目,则返回一个代号。用于onCreateViewHolder()方法中进行具体的布局加载。

@Override
public int getItemViewType(int position) {
if (position + 1 == getItemCount()) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}

有了ViewHolder之后,接下来就是要将ViewHolder和数据给绑定到一起来,在必须要实现的第二个方法onBindViewHolder(ViewHolder viewHolder,int i)中则建立起ViewHolder中视图与数据的关联。参数一个为对应的ViewHolder,一个为对应的位置。显然如果需要展示不同的布局,在onBindViewHolder()中通过判断viewHolder instanceof ViewHolder进行区分,对不同的布局中不同视图进行不同的数据关联。

最后getItemCount()是告知RecycleView,此Adapter到底要处理多少个对象。

2.2  Activity中的实现

mRcList = (RecyclerView) findViewById(R.id.rc_list);
mLayoutManager = new LinearLayoutManager(this);
mRcList.setLayoutManager(mLayoutManager);
mRcList.setHasFixedSize(true);
mSpinner = (Spinner) findViewById(R.id.spinner);
mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position == 0) {
mRcList.setLayoutManager(new LinearLayoutManager(MainActivity.this));
//设置分隔线
mRcList.addItemDecoration(new DividerItemDecoration(MainActivity.this, DividerItemDecoration.VERTICAL));
} else if (position == 1) {
mRcList.setLayoutManager(new GridLayoutManager(MainActivity.this, 3));
mRcList.addItemDecoration(new DividerGridItemDecoration(MainActivity.this));
}else if(position == 2){
//代表横着有10行
mRcList.setLayoutManager(new StaggeredGridLayoutManager(10,StaggeredGridLayoutManager.HORIZONTAL));
mRcList.addItemDecoration(new DividerGridItemDecoration(MainActivity.this));
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});

这里需要说明的是,现在SDK中提供了三种LayoutManager可以提供给RecyclerView使用,分别为LinearLayoutManager、GridLayoutManager、StaggeredGridLayoutManager。本例中使用一个Spinner实现一个动态的切换效果。

在设置的分隔线时,LinearLayoutManager设置为了系统默认的分隔线,如12行所示。如果想自定义,则可以在style中加入<item name="android:listDivider">@drawable/divider</item>,并在divider.xml中自行绘制矩形。而后两种布局中,默认的分割线是不合适的,DividerGridItemDecoration是自定义的。主要判断如果是最后一行,则不需要绘制底部;如果是最后一列,则不需要绘制右边,整个判断也考虑到了StaggeredGridLayoutManager的横向和纵向,所以稍稍有些复杂。有兴趣的可以在源码中自行解读。

mRcList.setHasFixedSize(true)的作用查了一下,解释如下:

//setHasFixedSize() is used to let the RecyclerView keep the same size.
//This information will be used to optimize itself.

最后进行数据初始化以及设置Adapter:

for(int i=0; i<=20 ; i++){
mData.add("Recycler");
}
mAdapter = new RecyclerAdapter(mData);
mRcList.setAdapter(mAdapter);

从效果图中可以看到,使用RecyclerView实现了两种不同的布局,通过背景颜色进行区分。而且,可以动态的为RecyclerView设置三种不同的布局。并且当点击主界面的删除按钮时,实现了删除最后一个Item的操作,这里notifyDataSetChanged()是通知Adapter数据发生了改变。

public void delRecycler(View view) {
if (mData.size()> 0) {
mData.remove(mData.size()- 1);
mAdapter.notifyDataSetChanged();
}
}

关于RecyclerView动画效果以及点击事件的设置方法,在Android开发——RecyclerView特性以及基本使用方法(二)中进行介绍。

源码下载地址点这里

Android开发——RecyclerView特性以及基本使用方法(一)的更多相关文章

  1. Android开发——RecyclerView特性以及基本使用方法(二)

    0.  前言 随着Android的发展,虽然ListView依旧重要,但RecyclerView确实越来越多的被大家使用.但显然并不能说RecyclerView就一定优于ListView,而是应该根据 ...

  2. Android开发之清除缓存功能实现方法,可以集成在自己的app中,增加一个新功能。

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 Android开发之清除缓存功能实现方法,可以集成在自己的app中,增加一个新功能. 下面是一个效果图 ...

  3. Android开发——RecyclerView实现下载列表

    本篇记录的是使用Jsoup框架爬取网页内容,结合Android的RecyclerView,从而实现批量下载小说的功能(也是我的APP星之小说下载器Android版的核心功能),思路仅供参考 本文使用了 ...

  4. Android开发 静态static类与static方法持有Context是否导致内存泄露的疑问

    简述 在Android开发的过程中,难免会使用单例模式或者静态方法工具类.我们会让它们持有一些外部的Context或者View一般有以下几种情况: 单例模式,类的全局变量持有Context 或 Vie ...

  5. Android开发中Parcelable接口的使用方法

    在网上看到很多Android初入门的童鞋都在问Parcelable接口的使用方法,小编参考了相关Android教程,看到里面介绍的序列化方法主要有两种分别是实现Serializable接口和实现Par ...

  6. Android开发----RecyclerView视图的学习

    RecyclerView RecyclerView是什么? RecyclerView是如今Android开发中最常用的控件,其相较于ListView和GridView的功能更为强大,优化了两者的各种不 ...

  7. Android开发环境搭建及常见问题解决方法

    转自: http://www.cnblogs.com/rwxwsblog/p/4769785.html 在移动互联网的时代,Android的份额早已超过了苹果.Android的出现无疑加速了移动互联网 ...

  8. 【转】Android开发中让你省时省力的方法、类、接口

    转载 http://www.toutiao.com/i6362292864885457410/?tt_from=mobile_qq&utm_campaign=client_share& ...

  9. 从零开始学android开发-用Intent启动Activity的方法

    启动另外一个Activity,可以有的方法有用setClass()和Component Name 1. 先说在setClass启动一个Activity的方法吧: Intent intent = new ...

随机推荐

  1. linux 网络和流量监控

    1.流量监控 工具iptraf 安装:sudo apt-get install iptraf 运行:sudo iptraf   2.网络监控扫描 参考:https://www.cnblogs.com/ ...

  2. Android开发工具Android Studio、Android SDK和Genymotion完全配置

    所谓“工欲善其事,必先利其器”.Android Studio 是谷歌推出一个Android集成开发工具,基于IntelliJ IDEA. 类似 Eclipse ADT,Android Studio 提 ...

  3. 【SPL标准库专题(1)】 SPL简介

    什么是SPL SPL是Standard PHP Library(PHP标准库)的缩写. 根据官方定义,它是"a collection of interfaces and classes th ...

  4. 如何在 Azure 中均衡 Windows 虚拟机负载以创建具有高可用性的应用程序

    负载均衡通过将传入请求分布到多个虚拟机来提供更高级别的可用性. 本教程介绍了 Azure 负载均衡器的不同组件,这些组件用于分发流量和提供高可用性. 你将学习如何执行以下操作: 创建 Azure 负载 ...

  5. SQL删除指定条件的重复数据,只保留一条

    BEGIN DELETE TB FROM TableName TB WHERE TB.ID IN (SELECT MIN(ID) FROM TableName TB2 GROUP BY TB2.Col ...

  6. 从零开始学习VoltDB

    1.什么是VoltDB? 是一个优化吞吐率的高性能集群开源SQLRDBMS(Database Management System),它是一个内存关系型数据库,既获得了nosql的良好可扩展性,高吞吐量 ...

  7. Django中的DateTimeField格式

    转自:http://www.nanerbang.com/article/5488/ 创建django的model时,有DateTimeField.DateField和TimeField三种类型可以用来 ...

  8. Linux uptime命令详解

    常见的命令展示 uptime 08:21:34 up 36 min, 2 users, load average: 0.00, 0.00, 0.00 #当前服务器时间: 08:21:34 #当前服务器 ...

  9. [python]如何理解uiautomator里面的 child, child_by_text, sibling,及使用场景

    如何理解uiautomator里面的 child, child_by_text, sibling,我们借助android原生的uiautomatorviewer抓取的控件来进行理解 以如下图进行详细讲 ...

  10. kdTree相关原理及c++实现

    kdTree概念 kd-tree或者k维树是计算机科学中使用的一种数据结构,用来组织表示k维空间中点的集合.它是一种带有其他约束条件的二分查找树.Kd-tree对于区间和近邻搜索十分有用.一般位于三维 ...