本文目录
- Listview和Recyclerview的区别(阿里一面,滴滴一面,被问到)
- 简单比较
- 布局上
- 局部刷新
- item view的重用
- ViewHolder
- 嵌套滑动机制
- 空数据处理
- Listview的二级缓存
- ActiveViews
- ScrapViews
- Recyclerview的四级缓存
- Recycler
- RecycledViewPool
- ViewCacheExtension
Listview和Recyclerview的区别(阿里一面,滴滴一面,被问到)
简单比较
listview:实现分割线很简单 ,
android:divider="@android:color/transparent"
android:dividerHeight="5dp"
继承重写BaseAdapter类; 自定义ViewHolder与convertView的优化(判断是否为null)
recyclerview: 继承重写RecyclerView.Adapter与RecyclerView.ViewHolder
设置LayoutManager,以及layout的布局效果
布局上
listview:布局比较单一,只支持竖直方向滑动
recyclerview:三种布局
1.线性布局,这个和listview相似 ,实现横向/纵向列表方向的item
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
2.网格布局,可以指定item的数量。
mRecyclerView.setLayoutManager(new GridLayoutManager(this,2));//可指定一行item的数目
3.瀑布流布局,可以指定列表方向,也可以指定同方向的item数量
局部刷新
1.listview:listview中通常刷新数据 notifyDataSetChanged() ,这种刷新是全局刷新的,每一个item的数据都会重新加载一次,这样很消耗资源,在一些需要频繁更新数据的场景,比如淘宝实时更新的界面,listview实现会很鸡肋
2.recyclerview:可以通过 notifyItemChanged() 来实现局部刷新
ps:不过如果要在ListView实现局部刷新,依然是可以实现的,当一个item数据刷新时,我们可以在Adapter中,实现一个onItemChanged()方法,在方法里面获取到这个item的position(可以通过getFirstVisiblePosition()),然后调用getView()方法来刷新这个item的数据
item view的重用
listview:默认每次加载一个新的item创建一个新view,引起内存增加,不过可以通过判断 convertView 是否为空来重用view。convertView 不为空,则不会产生新的条目, 屏幕上始终是一开始生成的那几个条目
recyclerview:默认实现重用view, RecyclerView复用item全部搞定,不需要像ListView那样setTag()与getTag();
ViewHolder
listview:viewHolder需要自定义,如果用getview去获取控件,则每次调用getview都要通过 findViewById 去获取控件, 如果控件个数过多,会严重影响性能 ,因为findViewById相对比较耗时,所以我们需要创建自定义viewHolder,通过getTag和setTag直接获取view
recyclerview:继承recyclerView.ViewHolder,默认需要重写viewHodler,使用已经封装好的
嵌套滑动机制
Android 5.0推出了嵌套滑动机制,在之前,一旦子View处理了触摸事件,父View就没有机会再处理这次的触摸事件,而嵌套滑动机制解决了这个问题,能够实现如下效果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VSmjvzkB-1622017525151)(G:\桌面\image\图像\20160808135831369)]
为了支持嵌套滑动,子View必须实现NestedScrollingChild接口,父View必须实现NestedScrollingParent接口。
而RecyclerView实现了NestedScrollingChild接口,而CoordinatorLayout实现了NestedScrollingParent接口,上图是实现CoordinatorLayout嵌套RecyclerView的效果。
listview: ListView 并不支持嵌套滚动机制
空数据处理
ListView 提供了 setEmptyView 这个 API 来让我们处理 Adapter 中数据为空的情况
recyclerview没有提供
Listview的二级缓存
RecycleBin:大意就是通过两级缓存来缓存view。
(RecycleBin在layout的过程中便于view重用,RecycleBin有两级存储:ActiveViews和ScrapViews。
ActiveViews存储的是layout开始的时候屏幕上那些view。layout结束后,所有ActiveViews中的view被移动到ScrapViews中。
ScrapViews中的views是那些可能被adapter重新用到的view,以避免重新创建不必要的view。)
ActiveViews
一级缓存,顾名思义活动等view,这些view是布局过程开始屏幕上的view。layout开始时这个数组被填充,layout结束,ActiveViews中的view移动到 ScrapViews。ActiveViews代表了一个连续范围的views,其第一个view的位置存储在FirstActivePosition变量中。
ScrapViews
二级缓存,顾名思义废弃的view,无序的被adapter的convertView使用的view的集合
ScrapViews是多个list组成的数组,数组的长度为viewTypeCount,每个item是个list,所以每个list缓存不同类型item布局的view,所以ScrapViews应该是下图的样子。
Recyclerview的四级缓存
RecycleView的四级缓存是由三个类共同作用完成的,Recycler、RecycledViewPool和ViewCacheExtension。
Recycler
用于管理已经废弃或者与RecyclerView分离的ViewHolder,这里面有两个重要的成员
1.屏幕内缓存 一级缓存,屏幕内缓存指在屏幕中显示的ViewHolder,这些ViewHolder会缓存在AttachedScrap、ChangedScrap中
ChangedScrap —>表示数据已经改变的viewHolder列表
AttachedScrap—>表示未与RecyclerView分离的ViewHolder列表
2.屏幕外缓存 二级缓存,当列表滑动出了屏幕时,ViewHolder会被缓存在 CachedViews ,其大小由ViewCacheMax决定,默认DEFAULT_CACHE_SIZE为2,可通过Recyclerview.setItemViewCacheSize()动态设置。
RecycledViewPool
三级缓存, RecycledViewPool类是用来缓存ViewHolder用,如果多个RecyclerView之间用setRecycledViewPool(RecycledViewPool)设置同一个RecycledViewPool,他们就可以共享ViewHolder。
ViewCacheExtension
四级缓存, 开发者可自定义的一层缓存,是虚拟类ViewCacheExtension的一个实例,开发者可实现方法getViewForPositionAndType(Recycler recycler, int position, int type)来实现自己的缓存。
“要不忘初心,永远谦逊”