RecyclerView 中 ViewHolder
ViewHolder 是 RecyclerView 架构中的核心组件,它作为视图持有者和复用单元,在列表性能和内存优化中扮演着至关重要的角色。
一、ViewHolder 的本质与作用
1. 核心定义
public abstract static class ViewHolder {public final View itemView; // 持有的列表项视图int mPosition = NO_POSITION; // 当前数据位置int mItemViewType = INVALID_TYPE; // 视图类型// ...
}
视图容器:持有 item 布局的所有视图引用
数据载体:连接数据和视图的桥梁
复用单元:作为 RecyclerView 缓存机制的基本单位
2. 核心价值
图表
代码
二、ViewHolder 的生命周期详解
1. 完整生命周期流程
2. 关键方法解析
方法 | 调用时机 | 典型用途 |
---|---|---|
onCreateViewHolder() | 创建新视图时 | 初始化视图组件 |
onBindViewHolder() | 绑定数据时 | 更新视图内容 |
onViewAttachedToWindow() | 视图进入屏幕 | 启动动画/加载 |
onViewDetachedFromWindow() | 视图离开屏幕 | 停止动画/释放 |
onViewRecycled() | 进入回收池 | 释放临时资源 |
三、ViewHolder 的实现模式
1. 基础实现(Java)
public class MyViewHolder extends RecyclerView.ViewHolder {TextView title;ImageView icon;public MyViewHolder(View itemView) {super(itemView);title = itemView.findViewById(R.id.tv_title);icon = itemView.findViewById(R.id.iv_icon);}public void bind(DataItem item) {title.setText(item.getTitle());Glide.with(itemView).load(item.getImageUrl()).into(icon);}
}
2. 最佳实践(Kotlin + ViewBinding)
class MyViewHolder(private val binding: ItemLayoutBinding
) : RecyclerView.ViewHolder(binding.root) {fun bind(item: DataItem) {binding.apply {tvTitle.text = item.titleGlide.with(root).load(item.imageUrl).into(ivIcon)// 点击事件处理root.setOnClickListener { // 通过接口回调}}}
}// Adapter中使用
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val binding = ItemLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false)return MyViewHolder(binding)
}
四、ViewHolder 与性能优化
1. 视图查找优化
// 传统方式(每次绑定都查找 - 不推荐)
void onBindViewHolder(ViewHolder holder, int position) {TextView title = holder.itemView.findViewById(R.id.tv_title);title.setText(data.get(position).title);
}// ViewHolder模式(只查找一次)
class ViewHolder {TextView title; // 初始化时查找void bind(DataItem item) {title.setText(item.title); // 直接使用}
}
2. 内存优化技巧
override fun onViewRecycled(holder: MyViewHolder) {// 释放图片资源Glide.with(holder.binding.ivIcon).clear()// 取消异步任务holder.currentTask?.cancel()// 重置视图状态holder.binding.progressBar.visibility = View.GONE
}
3. 视图类型优化
@Override
public int getItemViewType(int position) {DataItem item = dataList.get(position);if (item.hasImage()) return TYPE_IMAGE;if (item.isFeatured()) return TYPE_FEATURED;return TYPE_DEFAULT;
}// 创建不同ViewHolder
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {switch (viewType) {case TYPE_IMAGE:return new ImageViewHolder(...);case TYPE_FEATURED:return new FeaturedViewHolder(...);default:return new DefaultViewHolder(...);}
}
五、ViewHolder 的事件处理
1. 点击事件实现
class MyViewHolder(private val binding: ItemLayoutBinding,private val onClick: (Int) -> Unit
) : RecyclerView.ViewHolder(binding.root) {init {binding.root.setOnClickListener {val pos = adapterPositionif (pos != RecyclerView.NO_POSITION) {onClick(pos)}}}
}// Adapter中
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {return MyViewHolder(binding) { position ->// 处理点击事件val item = dataList[position]showDetail(item)}
}