RecyclerView 可以让您轻松高效地显示大量数据。您提供数据并定义每个列表项的外观,而 RecyclerView 库会根据需要动态创建元素。
顾名思义,RecyclerView 会回收这些单个的元素。当列表项滚动出屏幕时,RecyclerView 不会销毁其视图。相反,RecyclerView 会对屏幕上滚动的新列表项重用该视图。这种重用可以显著提高性能,改善应用响应能力并降低功耗。
关键对象和方法
- 添加
LayoutManager
负责布局RecyclerView的子布局 - 设置 RecyclerView.Adapter 负责添加和设置子布局的数据
- RecyclerViewDataObserver 数据监听
- dispatchLayout() 方法负责RecyclerView 布局页面
- LayoutManager.onLayoutChildren() 布局Item位置
Demo:
class RecyclerViewActivity : AppCompatActivity() {
var binding: ActivityRecyclerviewBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView<ActivityRecyclerviewBinding>(this, R.layout.activity_recyclerview)
initView()
}
private fun initView() {
var mAdapter = DemoAdapter(this)
//设置LayoutManager
binding!!.rvContent.layoutManager = LinearLayoutManager(this)
//设置 Adapter
binding!!.rvContent.adapter = mAdapter
var listData=ArrayList<String>()
listData.add("Android新控件")
listData.add("循环效果2:循环")
listData.add("Android")
listData.add("MotionLayout")
listData.add("Banner")
listData.add("循环效果2")
listData.add("Android新控件之MotionLayout实现Banner循环效果2:循环")
//刷新数据
mAdapter.addItems(listData)
}
// 自定义Adapter
class DemoAdapter(mContext: Context) : RecyclerView.Adapter<DemoViewHolder>() {
var mContext: Context? = null
var listData=ArrayList<String>()
init {
this.mContext = mContext
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DemoViewHolder {
var view = LayoutInflater.from(mContext).inflate(R.layout.item_demo, parent, false)
var viewHolder = DemoViewHolder(view)
return viewHolder
}
override fun onBindViewHolder(holder: DemoViewHolder, position: Int) {
var mHolder= holder
mHolder.getTextView().text=listData.get(position)
}
override fun getItemCount(): Int {
return listData.size
}
fun addItems(items:ArrayList<String>){
listData.addAll(items)
//刷新数据
notifyDataSetChanged()
}
}
// 自定义Holder
class DemoViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var rootView:View?=null
init {
rootView = view
}
fun getTextView():TextView{
var tvContent= rootView!!.findViewById<TextView>(R.id.tv_content)
return tvContent
}
}
}
源码分析
看到简单的Demo LayoutManager 管理了RecyclerView的布局,Adapter 填充了RecycerView子条目和绑定子条目的数据
所以咱们从Adapter 绑定数据数据看RecyceView的整体数据添加和页面布局
1.设置LayoutManager

/**
* Set the {@link LayoutManager} that this RecyclerView will use.
*
* <p>In contrast to other adapter-backed views such as {@link android.widget.ListView}
* or {@link android.widget.GridView}, RecyclerView allows client code to provide custom
* layout arrangements for child views. These arrangements are controlled by the
* {@link LayoutManager}. A LayoutManager must be provided for RecyclerView to function.</p>
*
* <p>Several default strategies are provided for common uses such as lists and grids.</p>
*
* @param layout LayoutManager to use
*/
// 设置 LayoutManager 配置布局的管理器
public void setLayoutManager(@Nullable LayoutManager layout) {
if (layout == mLayout) {
return;
}
// 设置停止滑动
stopScroll();
// TODO We should do this switch a dispatchLayout pass and animate children. There is a good
// chance that LayoutManagers will re-use views.
if (mLayout != null) {
// end all running animations
if (mItemAnimator != null) {
mItemAnimator.endAnimations();
}
mLayout.removeAndRecycleAllViews(mRecycler);
mLayout.removeAndRecycleScrapInt(mRecycler);
mRecycler.clear();
if (mIsAttached) {
mLayout.dispatchDetachedFromWindow(this, mRecycler);
}
mLayout.setRecyclerView(null);
mLayout = null;
} else {
mRecycler.clear();
}
// this is just a defensive measure for faulty item animators.
mChildHelper.removeAllViewsUnfiltered();
mLayout = layout;
if (layout != null) {
if (layout.mRecyclerView != null) {
throw new IllegalArgumentException("LayoutManager " + layout
+ " is already attached to a RecyclerView:"
+ layout.mRecyclerView.exceptionLabel());
}
mLayout.setRecyclerView(this);
if (mIsAttached) {
mLayout.dispatchAttachedToWindow(this);
}
}
mRecycler.updateViewCacheSize();
requestLayout();
}
2.设置Adapter适配器

2.1配置数据

2.2 设置数据观察者 RecyclerViewDataObserver mObserver


2.3 notifyDataSetChanged 添加数据以及数据刷新
Adapter.notifyDataSetChanged()
2.4 刷新数据 调用到 AdapterDataObservable mObservable 数据更新了

2.5 RecyclerView Adapter的mObservers 调用注册的 mObservers中的RecycrViewDataObserver

2.5.1 RecycrViewDataObserver (设置Adapter的时候注册的数据更新的观察者)

2.5.2 RecycrViewDataObserver (设置Adapter的时候注册的数据更新的观察者)

2.6 更新或者添加数据 RecycrViewDataObserver 收到监听更新布局

2.7 重新 布局页面

2.8 重新 布局页面 执行 dispatchLayoutStep2()

2.9 LayoutManager 执行 onLayoutChildren() 布局 子布局

2.10 LayoutManager 是第一步试着的LayoutManager

2.11 LayoutManager 布局子条目的位置

总结:
RecyelerView 绘制的主要方法就是设置LayoutManager Adapter RecyclerViewDataObserver dispatchLayout() dispatchLayoutStep2() mLayout.onLayoutChildren(mRecycler, mState); 主要是这几个对象以及方法 执行了 RecyclerView的刷新以及布局的流程 . LayoutManager 负责布局Item的位置 Adapter 负责创建和填充数据 RecyclerViewDataObserver 监听 数据的更新 dispatchLayout () dispatchLayoutStep2() 调用LayoutManager 的onLayoutChildren布局数据
网友评论