RecyclerView 中 ViewHolder

发布于:2025-08-10 ⋅ 阅读:(20) ⋅ 点赞:(0)

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)
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到