4. Adapter 基础:创建 Adapter 类,理解三个核心方法

好,咱们今天来聊聊 RecyclerView 里最核心的一个角色——Adapter。说实话,我刚接触 Android 开发那会儿,总觉得 Adapter 是个很玄乎的东西。它到底在干什么?为什么非得写这三个方法?

其实说白了,Adapter 就是个「翻译官」。它把咱们的数据(比如一个列表的字符串、对象),翻译成 RecyclerView 能看懂的一个个列表项。你想想看,RecyclerView 本身只负责「展示」和「回收」,它可不知道你的数据长什么样。这时候就需要 Adapter 在中间搭个桥。

4.1 Adapter 的三个核心方法

每个 Adapter 都必须实现三个方法,缺一不可。我当年第一次写的时候,还漏掉了 getItemCount(),结果列表一片空白,找了半天 bug……嗯,咱们一个个来看。

方法 作用 调用时机
onCreateViewHolder 创建列表项的视图容器(ViewHolder) 当 RecyclerView 需要新的视图时
onBindViewHolder 将数据绑定到 ViewHolder 上 当视图需要显示数据时
getItemCount 告诉 RecyclerView 一共有多少条数据 布局、滚动、刷新时都会调用

4.2 手写一个最简单的 Adapter

咱们直接上代码。假设我们要展示一个水果列表:

class FruitAdapter(private val fruitList: List<String>) :
    RecyclerView.Adapter<FruitAdapter.FruitViewHolder>() {

    // 第一步:创建 ViewHolder
    class FruitViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val textView: TextView = itemView.findViewById(R.id.tv_fruit_name)
    }

    // 第二步:创建视图(只调用一次,用于生成新的列表项)
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_fruit, parent, false)
        return FruitViewHolder(view)
    }

    // 第三步:绑定数据(每次视图出现在屏幕上时调用)
    override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {
        holder.textView.text = fruitList[position]
    }

    // 第四步:告诉 RecyclerView 数据总量
    override fun getItemCount(): Int = fruitList.size
}

这段代码看着简单,但每个方法背后都有讲究。我一个个拆开讲。

4.3 onCreateViewHolder:视图的「工厂」

这个方法只做一件事:把布局文件变成 ViewHolder。它不会频繁调用,RecyclerView 会复用已经创建好的 ViewHolder。

我在项目中遇到过一个问题:有人在 onCreateViewHolder 里做了大量初始化操作,比如加载图片、设置监听器。其实没必要,这些操作应该放到 onBindViewHolder 里。为什么?因为 onCreateViewHolder 只调用几次,而 onBindViewHolder 每次数据变化都会调用。你想想看,把耗时操作放在只调用几次的地方,是不是更合理?

个人习惯:我一般只在 onCreateViewHolder 里做视图的「骨架」搭建,比如设置点击事件、初始化动画。数据相关的操作一律放到 onBindViewHolder

4.4 onBindViewHolder:数据的「搬运工」

这个方法才是真正干活的地方。它把数据从列表里取出来,塞到 ViewHolder 的控件里。

注意一个细节:position 参数。它代表当前列表项在数据源中的索引。但如果你在列表中间插入或删除了数据,这个 position 可能会变。我曾经踩过这个坑——在 onBindViewHolder 里直接用 position 做缓存 key,结果数据错乱了。

避坑指南:不要在 onBindViewHolder 里做耗时操作,比如网络请求、数据库读写。RecyclerView 的滚动是 UI 线程执行的,你卡一下,用户就能感觉到掉帧。我曾经因为在这里加载图片没做缓存,导致列表滑动卡成 PPT……嗯,后来老老实实用了 Glide。

4.5 getItemCount:数据的「计数器」

这个方法最简单,但最容易出错。它返回的是列表的总条目数。如果返回 0,RecyclerView 什么都不显示。如果返回负数,直接崩溃。

我建议你永远返回 list.size 或者 dataSet.size。不要自己算,不要写死。数据变了,这个值自然就变了。

4.6 知识体系:Adapter 的核心逻辑

下面这张图帮你理清 Adapter 的工作流程。我画的时候特意把「数据源」「ViewHolder 池」「RecyclerView」三者的关系标了出来:

Adapter 工作流程 数据源 List<String> fruitList size getItemCount() 返回总条目数 总数 RecyclerView 知道要展示多少项 需要新视图时 onCreateViewHolder 创建 ViewHolder 存入 ViewHolder 池 复用/回收 取出复用 onBindViewHolder 绑定数据到视图 读取数据 显示

4.7 完整的使用示例

光有 Adapter 还不够,咱们得把它和 RecyclerView 连起来。在 Activity 或 Fragment 里这样写:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
        val fruits = listOf("苹果", "香蕉", "橘子", "葡萄", "西瓜")

        // 设置布局管理器
        recyclerView.layoutManager = LinearLayoutManager(this)
        // 创建 Adapter 并设置
        val adapter = FruitAdapter(fruits)
        recyclerView.adapter = adapter
    }
}

这里有个小细节:一定要先设置 layoutManager,再设置 adapter。顺序反了虽然不会崩溃,但 RecyclerView 可能会多走一些不必要的测量流程。我个人习惯是先设布局管理器,再设适配器。

4.8 小结

咱们今天把 Adapter 的三个核心方法讲透了:

  • onCreateViewHolder:创建视图的工厂,只调用几次
  • onBindViewHolder:绑定数据的搬运工,频繁调用
  • getItemCount:告诉 RecyclerView 数据总量

这三个方法就像 Adapter 的「三驾马车」,缺一不可。你写的时候只要记住:创建视图、绑定数据、返回数量,顺序别搞混就行。

核心要点:

  • ViewHolder 是视图的容器,不要在里面做耗时操作
  • onBindViewHolder 的 position 是动态的,别用它做永久缓存
  • getItemCount 返回 0 时列表不显示,返回负数时崩溃
  • 先设 layoutManager,再设 adapter

嗯,Adapter 的基础就这些。下一节咱们会深入 ViewHolder 的优化技巧,看看怎么让列表滑得更丝滑。


公众号:蓝海资料掘金营,微信deep3321