Android Recyclerview与带有Viewholder的ListView


148

我最近遇到了RecyclerView与Android 5.0一起发布的android 系统,它似乎RecyclerView只是一个封装的传统,ListView并结合了ViewHolder模式,该模式促进了视图的重用,而不是每次都创建它。

使用的其他好处是RecyclerView什么?如果两者在性能方面具有相同的效果,为什么还要选择RecyclerView`?

编辑

我发现人们也提出了类似的问题,并且答案不是确定性的,因此将其添加到此处以进行记录。

Recyclerview与Listview

我们应该使用RecyclerView替换ListView吗?

为什么RecyclerView没有onItemClickListener()?RecyclerView与Listview有何不同?


4
因为RecyclerView使用更好的API可以更快,更通用。诸如动​​画添加或删除项目之类的事情已经在中实现,RecyclerView而您无需执行任何操作。毫无疑问,将您ListView的垃圾桶扔进去,这RecyclerView是在窃取节目。
Xaver Kapeller

4
您可以将布局管理器与RecyclerView关联,因此它们不仅限于垂直滚动列表。这是非常强大的附加功能。
艾伦(Alan)

@Alan-“不限于垂直滚动列表”是什么意思?您是说回收视图也可以充当Gridviews和ListViews的“占位符”吗?
Mushtaq Jameel

@XaverKapeller-如果您可以列出两者之间的差异并回答问题而不是发表评论,那就太好了,这样可以帮助我和将来对同一个事情感到奇怪的其他人?
Mushtaq Jameel

@Alan-您能否提供一些有关您的意思的详细信息并回答问题,而不是发表评论。感谢您抽出
宝贵

Answers:


289

随着Android Lollipop的问世,RecyclerView正式问世。与ListView相比, RecyclerView更加强大,灵活并且具有重大改进。我将尽力为您提供详细的了解。

1)ViewHolder模式

在ListView中,建议使用ViewHolder模式,但这绝不是强制性的。如果是RecyclerView,则使用RecyclerView.ViewHolder类是强制性的。这是ListView和RecyclerView之间的主要区别之一。

它使RecyclerView中的事情变得更加复杂,但是我们在ListView中面临的许多问题都得到了有效解决。

2)布局管理器

这是RecyclerView带来的另一项重大改进。在ListView中,唯一可用的视图类型是垂直ListView。甚至没有实现水平ListView的官方方法。

现在使用RecyclerView,我们可以

i)LinearLayoutManager-支持垂直和水平列表,

ii)StaggeredLayoutManager-支持像交错列表这样的Pinterest,

iii)GridLayoutManager-支持显示在Gallery应用程序中看到的网格。

最好的是,我们可以根据需要动态地执行所有这些操作。

3)项目动画师

ListView缺乏对好的动画的支持,但是RecyclerView给它带来了一个全新的维度。使用RecyclerView.ItemAnimator类,对视图进行动画处理变得非常容易和直观。

4)物品装饰

对于ListViews,动态装饰项目(例如添加边框或分隔线)从未如此简单。但是在使用RecyclerView的情况下,RecyclerView.ItemDecorator类为开发人员提供了巨大的控制权,但使事情变得更加耗时和复杂。

5)OnItemTouchListener

借助 ListView的AdapterView.OnItemClickListener接口,拦截ListView上的项目单击非常简单。但是RecyclerView通过RecyclerView.OnItemTouchListener不再支持,请参考AndroidX)为其开发人员提供更多功能和控制权,但它会使开发人员的工作变得复杂。

简而言之,RecyclerView比ListView更可自定义,并为其开发人员提供了很多控制和功能。


34
好答案。还有两个额外的优点:RecyclerView在可见条目的前面和后面准备视图,如果您在后台获取位图,这将非常有用。性能显着提高,特别是如果您使用RecyclerView.setHasFixedSize。旧的ListView基于以下前提:无法预先计算或缓存列表中条目的大小,这会在滚动和执行布局时引起疯狂的麻烦。需要一段时间来习惯它,但是一旦您习惯了,就永远不会回头。
罗宾·戴维斯

@RobinDavies非常好。感谢您的通知。但是,如果项目的大小不同,那将是没有意义的。
Aritra Roy 2015年

@AritraRoy Recyclerview仅支持棒棒糖或api 14+(android 4+)吗?...当我读到“棒棒糖之后:在大多数地方
Animesh Mangla 2015年

2
嘿,Aritra,当与ListView进行比较时,如果ListView也使用ViewHolder Pattern,那么哪个行为更有效?使用fps或其他类似标准时,RecylerView会更好吗?
thx〜– RxRead

@RxRead:请参阅Robin的评论,他根据性能将RecyclerView与ListView与视图持有者模式区分开。
Parag Kadam's

10

使用的另一个好处RecycleView是动画,它可以用两行代码完成

RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator();
        recyclerView.setItemAnimator(itemAnimator);

但是小部件仍然是原始的,例如,您不能创建headerfooter


5
这样,您将永远无法创建页眉和页脚。它们只是适配器中的其他视图类型。列表视图将适配器包装在内,HeaderViewListAdapter并在后台添加标题支持。与RecyclerView您一起掌控一切。
Eugen Pechanec

RecyclerView默认情况下使用DefaultItemAnimator。那你为什么要用这个代码呢?
阿西拉·雷迪

9

好吧,我挖这么点点发现比尔飞利浦这些宝石的文章RecycleView

RecyclerView可以做的比ListView还要多,但是RecyclerView类本身的职责要比ListView少。开箱即用,RecyclerView不会:

  • 在屏幕上放置项目
  • 动画视图
  • 处理滚动以外的任何触摸事件

所有这些东西都放入了ListView中,但是RecyclerView使用协作器类来完成这些工作。

您创建的ViewHolders也更加强大。他们子类化 RecyclerView.ViewHolder,它具有许多方法RecyclerView 用途。ViewHolders知道他们当前绑定到的位置,以及哪个项目ID(如果有)。在此过程中,ViewHolder 已被封为爵士。它过去一直是ListView的工作,可以保留整个项目视图,而ViewHolder仅保留其中的一小部分。

现在,ViewHolder保留了该ViewHolder.itemView 字段中的所有内容,这是在ViewHolder的构造函数中为您分配的。


4

比尔·菲利普Bill Phillip)的文章有更多内容(请继续阅读!),但我认为指出以下几点很重要。

在ListView中,如何处理单击事件存在一些歧义:单个视图应该处理这些事件,还是ListView通过OnItemClickListener处理它们?但是,在RecyclerView中,ViewHolder处于明确的位置,可以充当处理这些详细信息的行级控制器对象。

前面我们看到LayoutManager处理定位视图,而ItemAnimator处理动画。ViewHolder是最后一部分:它负责处理RecyclerView显示的特定项目上发生的任何事件。


2

ListView与Glide图像加载器一起使用,具有增加的内存。然后我用替换ListViewRecyclerView。它不仅在编码上更加困难,而且比导致更多的内存使用ListView。至少在我的项目中。

在另一项活动中,我使用了一个复杂的列表EditText's。在其中一些输入方法可能会有所不同,也TextWatcher可以应用。如果使用ViewHolderTextWatcher在滚动过程中如何替换?因此,我使用了ListView不带的ViewHolder,并且可以正常工作。


我使用了一个没有ViewHolder的ListView,它可以工作。糟糕的主意... 在滚动过程中如何替换TextWatcher?无需替换它...只需TextWacher在重用后应将数据放入不同的容器中……而且可以非常容易地完成
Selvin

@Selvin,谢谢您的意见。现在,我无法编辑该项目。TextWatcher屏幕上有几个。可能您是正确的,但我无法确认。
CoolMind

1

在上/下滚动时重用单元格 -这可以通过在listView适配器中实现View Holder来实现,但这是可选的,而在RecycleView中则是编写适配器的默认方式。

将列表与其容器解耦 -因此,您可以通过设置LayoutManager在运行时轻松地将列表项放在不同容器(linearLayout,gridLayout)中。

例:

mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//or
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 2));
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));
  • 对常见的列表动作进行动画处理。

  • 动画被解耦并委托给ItemAnimator

关于RecyclerView的更多信息,但是我认为这些是主要的观点。

布局管理器

i)LinearLayoutManager-支持垂直和水平列表,

ii)StaggeredLayoutManager-支持像交错列表这样的Pinterest,

iii)GridLayoutManager-支持显示在Gallery应用程序中看到的网格。

最好的是,我们可以根据需要动态地执行所有这些操作。


1

1.查看持有人

在ListView中,定义视图所有者是保留视图引用的建议方法。但这不是强迫。尽管没有这样做,但ListView使用了显示过时的数据。不使用视图持有者的另一个主要缺点可能导致每次通过id查找视图的操作繁重。这导致了ListViews的延迟。

通过使用RecyclerView.ViewHolder类,可以在RecylerView中解决此问题。这是RecyclerView和ListView的主要区别之一。在实现RecyclerView时,此类用于定义ViewHolder对象,适配器将其用于将ViewHolder与位置绑定。这里要注意的另一点是,在实现RecyclerView适配器时,必须提供ViewHolder。这使实现有些复杂,但是解决了ListView中面临的问题。

2.布局管理器

说到ListView,只有一种类型的ListView可用,即垂直ListView。您不能使用水平滚动来实现ListView。我知道有多种方法可以实现水平滚动,但是我相信它并不是设计成可以这种方式工作的。

但是现在,当我们查看Android RecyclerView与ListView时,我们也支持水平集合。实际上,它支持多种类型的列表。为了支持多种类型的列表,它使用RecyclerView.LayoutManager类。这是ListView没有的新功能。RecyclerView支持三种类型的预定义布局管理器:

LinearLayoutManager –对于RecyclerView,这是最常用的布局管理器。这样,我们可以创建水平和垂直滚动列表。StaggeredGridLayoutManager –通过此布局管理器,我们可以创建交错列表。就像Pinterest屏幕一样。GridLayoutManager –此布局管理器可用于显示网格,就像任何图片库一样。

3.项目动画师

列表中的动画是一个全新的维度,它具有无限的可能性。因此,在ListView中,没有特殊的规定可以使人动画,添加或删除项目。后来,随着Android的发展,Google的Chet Haase在此视频教程中建议使用ViewPropertyAnimator来实现ListView中的动画。

另一方面,比较Android RecyclerView与ListView,它具有RecyclerView.ItemAnimator类,用于处理动画。通过此类,可以为项目添加,删除和移动事件定义自定义动画。如果不需要任何自定义,它还提供一个DefaultItemAnimator。

4.适配器

ListView适配器易于实现。他们有一个主要的方法getView,在这里曾经发生过所有的魔术。视图绑定到的位置。他们还曾经有一个有趣的方法registerDataSetObserver,可以在适配器中设置一个观察者。此功能也存在于RecyclerView中,但是使用了RecyclerView.AdapterDataObserver类。但是支持ListView的一点是它支持适配器的三种默认实现:

ArrayAdapter CursorAdapter SimpleCursorAdapter而RecyclerView适配器具有ListView适配器具有的所有功能,但对DB游标和ArrayLists的内置支持除外。从现在开始,在RecyclerView.Adapter中,我们必须进行自定义实现以向适配器提供数据。就像BaseAdapter用于ListViews一样。尽管如果您想了解有关RecyclerView适配器实现的更多信息,请参考Android RecyclerView示例。

5.通知数据变更

使用ListView时,如果更改了数据集,则必须调用基础适配器的notifyDataSetChanged方法来刷新数据。或将setNotifyOnChange方法设置为true,以防您希望自动调用notifyDataSetChanged方法。但是在这两种情况下,列表上的结果都很重。基本上,它刷新列表的视图。

但是相反,在RecyclerView适配器中,如果单个项目或一系列项目已更改,则有相应的方法来通知更改。它们分别是notifyItemChanged和notifyItemRangeChanged,还有更多类似的东西:

notifyItemInsterted notifyItemMoved notifyItemRangeInsterted notifyItemRangeRemoved当然,它具有刷新整个列表的原始方法,即notifyDataSetChanged,它通知适配的整个数据集已更改。

6.物品装饰

要在ListView中显示自定义分隔符,可以在ListView XML中轻松添加以下参数:

XHTML android:divider =“ @ android:color / transparent” android:dividerHeight =“ 5dp” 1 2 android:divider =“ @ android:color / transparent” android:dividerHeight =“ 5dp”关于Android RecyclerView的有趣之处在于,截至目前,默认情况下它不会显示项目之间的分隔线。尽管Google的人员一定有意保留此设置以进行自定义。但这极大地增加了开发人员的工作量。如果希望在项目之间添加分隔符,则可能需要使用RecyclerView.ItemDecoration类进行自定义实现。

或者,您可以通过使用官方样本中的以下文件来应用黑客:DividerItemDecoration.java

7. OnItemTouchListener

列表视图过去具有用于检测点击的简单实现,即通过使用AdapterView.OnItemClickListener接口。

但另一方面,RecyclerView.OnItemTouchListener接口用于检测Android RecyclerView中的触摸事件。它使实现复杂一些,但可以更好地控制开发人员以拦截触摸事件。官方文档指出,它对于手势操作很有用,因为它在将触摸事件传递给RecyclerView之前会拦截触摸事件。


1

RecyclerView是作为ListView的改进而创建的,因此可以,您可以使用ListView控件创建一个附加列表,但是使用RecyclerView更容易,因为:

  1. 在上/下滚动时重用单元格:这可以通过在ListView适配器中实现View Holder来实现,但这是可选的,而在RecycleView中则是编写适配器的默认方式。

  2. 将列表从其容器中解耦:因此,您可以在运行时通过设置LayoutManager轻松地将列表项放在不同的容器(linearLayout,gridLayout)中。

mRecyclerView =(RecyclerView)findViewById(R.id.my_recycler_view); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mRecyclerView.setLayoutManager(new GridLayoutManager(this,2));

  1. 对常见的列表动作进行动画处理:将动画解耦并委派给ItemAnimator。关于RecyclerView的更多信息,但是我认为这些是主要的观点。

因此,总而言之,RecyclerView是一种用于处理“列表数据”的更灵活的控件,该控件遵循关注委托的模式,仅将一项任务(回收项目)留给自己。


0

如果使用RecycleView,首先需要更多的efford来进行设置。您需要给更多的时间来设置简单的项目onclick,边框,触摸事件和其他简单的东西。但是最终产品将是完美的。

因此,决定权属于您。我建议,如果您设计简单的应用程序(例如电话簿加载),只需单击项目就足够了,则可以实现listview。但是,如果您设计的社交媒体主页具有无限滚动性。物品之间有几种不同的装饰,比使用回收视图更能控制单个物品。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.