1、RecycleView :
- 一个用于大量数据展示的新控件,可以用来代替传统的ListView,更加强大和灵活。
2、RecycleView的结构:
- RecycleView的每一个列表项都是作为一个view来显示的。RecycleView的任务是定位、回收子列表,其他功能还需要Adapter类和ViewHolder的支持。
- ViewHolder:容纳视图
- Adapter作用:
1、负责创建ViewHolder
2、一个桥梁,绑定ViewHolder至模型层数据。
RecycleView 与Adapter交互
-
Recycleview本身是不能创建用来显示的子视图的,它负责间接创建ViewHolder,ViewHolder引用这itemView;RecycleView显示大量数据时,重复利用的是ViewHolder,而不是itemView:
3、RecycleView的使用:
代码是在MainActivity中写的:
第一步:在MainActivity对应的xml布局文件导入RecycleView,id为mRecyclerView
第二步:实现RecycleView的layoutManager,介绍三种布局方式:
- LinearLayoutManager:线性布局
mRecyclerView.layoutManager = LinearLayoutManager(context上下文,显示方向,是否反转显示)
- GridLayoutManager:网格布局,线性布局是单行显示,网格布局可以设置并行显示的列数(竖直方向显示)
mRecyclerView.layoutManager = GridLayoutManager(上下文,显示行(列)数,显示方向,是否逆转显示)
- StaggeredGridLayoutManager:瀑布布局,类似淘宝商品展示的效果,可以交错显示
mRecyclerView.layoutManager = StaggeredGridLayoutManager(显示行(列)数,显示方向)
![](https://img.haomeiwen.com/i15368151/8c80bfe0883a5f97.png)
第三步:设置RecycleView的Adapter适配器:
- 因为Adapter是一个抽象类,所以最好是自定义一个类继承于Adapter
在MainActivity创建适配器(适配器名:MAdapter)
mRecyclerView.adapter = MAdapter().also {
// 在创建适配器是传入用于显示的数据
it.data = dataSource
}
MAdapter类中:
// 继承于Adapter时,Adapter要传入一个继承于ViewHolder或是继承于ViewHolder的子类
// 但是由于ViewHolder也是一个抽象类,所以也写一个继承于它的子类
class MAdapter : RecyclerView.Adapter<MAdapter.MyViewHolder>() {
// 接收MainActivity在创建Adapter时传递过来的数据
lateinit var data: MutableList<Int>
// 继承于Adapter是必须实现的三个抽象方法
// 创建ViewHolder,并解析RecycleView的子列表对应的xml布局文件,用以确定自己item的显示样式
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
// xml布局解析
var inflater = LayoutInflater.from(parent.context)
var itemView = inflater.inflate(R.layout.fot_item, parent, false)
return MyViewHolder(itemView)
}
// 获取子项的个数
override fun getItemCount(): Int {
return data.size
}
// 当item的显示风格不相同时,重写此方法(当然在封装数据时,
// 要将子项显示模式封装进去,在这里调用返回给onCreateViewHolder函数的viewType参数,然后进行判断就行了)
override fun getItemViewType(position: Int): Int {
// 获取position对应的数据模型的显示样式
}
// 将视图和数据进行绑定(getItemCount只会调用一次,onCreateViewHolder当创建的ViewHolder数量足够时,也
// 不会再调用。但是,只要RecycleView在滚动,显示的数据在更新,onBindViewHolder就会一直调用)
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.icon.setImageResource((data[position]))
}
// 在继承于ViewHolder时,系统默认一定要出人一个参数:itemView,ViewHolder管理的View视图
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
// 获取视图
var icon = itemView.findViewById<ImageView>(R.id.item_icon)
}
}
第四步:给RecycleView的item添加边距:
当然,也可以在定义item的xml布局是添加边距
mRecyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
super.getItemOffsets(outRect, view, parent, state)
outRect.set(20, 20, 20, 20)
}
})
第五步:让每个item按页显示
// PagerSnapHelper().attachToRecyclerView(mRecyclerView)
LinearSnapHelper().attachToRecyclerView(mRecyclerView)
第六步:实现item的点击事件
- 点击事件是RecycleView的缺点之一,因为它的点击、长按事件,需要自己写。
- 在自己的Adapter中定义一个高阶函数监听item的点击事件,当被点击时,将当前item的position传到MainActivity
// 在NewsAdapter下定义高阶函数:
var callBack:((Int)->Unit)? = null
// 在onBindViewHolder监听item的点击事件,也可以在onCreateViewHolder中监听
override fun onBindViewHolder(holder: NewsViewHolder, position: Int) {
holder.itemView.setOnClickListener(){
callBack?.let {
it(position)
}
}
}
// 在MainActivity中接收item点击事件传递过来的数据
var mRecyclerView= NewsAdapter()
mRecyclerView.callBack = {
Log.v("yk", "第 $it 被点击了")
}
RecycleView优化策略:
- 不要在onBindViewHolder中设置监听器,在onCreateViewHolder中设置监听器
- 使用DiffUtil
- RecyclerView.setHasFixedSize()方法
- LinearLayoutManager.setInitialPrefetchitemCount()方法
-
多个RectclerView共用RecycledViewPool.
image.png
LIstVIew与RecycleView对比:
网友评论