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」三者的关系标了出来:
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