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.title
Glide.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 = adapterPosition
if (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)
}
}