Android Studio(Kotlin)中继承RecyclerView.ViewHolder的作用是什么
自定义ViewHolder继承
RecyclerView.ViewHolder(view)的作用 你觉得它除了接收view参数没有显式作用,是因为父类的核心逻辑全是给RecyclerView框架内部调用的,不需要你主动重写或者调用,和Adapter需要你重写业务方法的定位完全不一样,具体作用分三点:
- 统一存储Item根视图引用
你传入构造函数的view是列表单个条目的根布局,父类RecyclerView.ViewHolder会把它存在公开的itemView常量字段里。RecyclerView框架在做条目测量、布局摆放、触摸事件分发、出入场动画、可见性判断的时候,全是直接读取这个itemView操作,不需要你手动管理根视图的引用。你子类里写的textView这类属性,只是根视图下的子控件,是给你自己绑定数据用的,框架不关心这些。 - 作为列表复用机制的核心载体
RecyclerView的回收缓存(比如四级缓存里的RecycledViewPool、CachedViews)存储的单元从来不是裸的View对象,而是ViewHolder实例。父类内部已经封装好了所有复用相关的状态字段:当前绑定的条目位置、viewType、是否在屏幕可见、是否已被回收、绑定过的旧数据ID、是否处于预加载状态等等,这些状态全是RecyclerView做复用时判断逻辑的核心依据,你继承之后直接获得这些能力,不需要自己维护任何状态。 - 提供通用的条目操作能力
你平时常用的bindingAdapterPosition(获取当前条目最新的适配器位置)、itemViewType(获取当前条目类型)、setIsRecyclable()(控制条目是否允许回收)、条目点击事件设置这些能力,全是父类ViewHolder已经实现好的,直接调用就行,不需要自己重复实现。
和Adapter的差异原因
RecyclerView.Adapter的定位是「数据和视图的绑定桥接层」,框架根本不知道你要加载什么布局、数据有多少条、怎么把数据塞到条目的控件里,所以必须强制你重写onCreateViewHolder、onBindViewHolder、getItemCount三个方法,把业务逻辑告诉框架。
而ViewHolder的定位是「框架内部使用的复用单元包装类」,核心逻辑全是给RecyclerView内部调度用的,你只要把根视图传给它完成初始化,剩下的内部逻辑父类已经全部实现,你只需要在子类里加业务需要的子控件引用就行,自然不需要重写额外方法。
小提示:你示例代码里给ItemViewHolder构造函数加的
private val view: View是多余的,父类已经公开了itemView属性,直接用itemView.findViewById(R.id.item_title)即可,不需要重复存储根视图引用。
补全后的完整可运行参考代码:
class ItemAdapter( private val context: Context, private val dataset: List<Affirmation> ) : RecyclerView.Adapter<ItemAdapter.ItemViewHolder>() { // 自定义ViewHolder只需要持有子控件引用即可,父类已经处理了所有基础逻辑 class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { val textView: TextView = view.findViewById(R.id.item_title) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { // 加载条目布局,传入ViewHolder构造函数,父类会自动存储根view引用 val adapterLayout = LayoutInflater.from(parent.context) .inflate(R.layout.list_item, parent, false) return ItemViewHolder(adapterLayout) } override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { // 直接用holder里持有的子控件引用绑定数据 val item = dataset[position] holder.textView.text = context.resources.getString(item.stringResourceId) } override fun getItemCount() = dataset.size }
内容的提问来源于stack exchange,提问作者Theprogrammingnoob
相关产品推荐
相关产品推荐

