Kotlin安卓APP点击添加按钮崩溃,抛出NullPointerException
解决RecyclerView Adapter空指针崩溃问题
崩溃日志
FATAL EXCEPTION: main
Process: com.example.bbar, PID: 25930
java.lang.NullPointerException
at com.example.bbar.ui.home.FoodlistadapterKt.getBinding(foodlistadapter.kt:16)
at com.example.bbar.ui.home.FoodlistadapterKt.access$getBinding(foodlistadapter.kt:1)
at com.example.bbar.ui.home.Foodlistadapter.onBindViewHolder(foodlistadapter.kt:57)
at com.example.bbar.ui.home.Foodlistadapter.onBindViewHolder(foodlistadapter.kt:18)
问题根源
- 全局静态Binding未初始化:你在
Foodlistadapter中定义了全局静态的FooditemBinding变量,但从未对其赋值,调用binding!!时直接触发空指针。 - 加载错误布局:
onCreateViewHolder中加载了fragment_home布局,而非RecyclerView Item对应的fooditem布局,导致无法找到item内的控件。 - ViewHolder未持有独立Binding:没有让每个ViewHolder持有对应item的Binding实例,错误依赖全局未初始化的Binding。
修复后的完整foodlistadapter.kt代码
package com.example.bbar.ui.home import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.example.bbar.databinding.FooditemBinding class Foodlistadapter( private val foods: MutableList<food> ) : RecyclerView.Adapter<Foodlistadapter.FoodlistViewHolder>() { // ViewHolder持有当前item的Binding实例 inner class FoodlistViewHolder(val binding: FooditemBinding) : RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FoodlistViewHolder { // 加载正确的Item布局 val binding = FooditemBinding.inflate(LayoutInflater.from(parent.context), parent, false) return FoodlistViewHolder(binding) } fun addFood(food: food) { foods.add(food) notifyItemInserted(foods.size - 1) } fun deleteFood() { foods.removeAll { it.isChecked } notifyDataSetChanged() } private fun toggleStrikeThrough(textView: android.widget.TextView, isChecked: Boolean) { textView.paintFlags = if (isChecked) { textView.paintFlags or STRIKE_THRU_TEXT_FLAG } else { textView.paintFlags and STRIKE_THRU_TEXT_FLAG.inv() } } override fun onBindViewHolder(holder: FoodlistViewHolder, position: Int) { val currentFood = foods[position] holder.binding.apply { tvFood.text = currentFood.name tvCalories.text = currentFood.calories.toString() cbDelete.isChecked = currentFood.isChecked toggleStrikeThrough(tvFood, currentFood.isChecked) cbDelete.setOnCheckedChangeListener { _, isChecked -> toggleStrikeThrough(tvFood, isChecked) currentFood.isChecked = isChecked } } } override fun getItemCount(): Int = foods.size }
关键修改点
- 移除全局静态Binding变量,改为让每个
FoodlistViewHolder持有对应item的Binding实例,确保每个item有独立的控件引用。 onCreateViewHolder中使用FooditemBinding.inflate()加载正确的item布局,替代原错误的fragment_home布局。onBindViewHolder中通过holder.binding访问当前item的控件,彻底避免空指针。- 修正
deleteFood中的变量名冲突(原代码参数名与类成员变量重名)。 - 修正复选框状态同步逻辑,直接将
isChecked赋值给currentFood.isChecked,避免逻辑错误。
额外优化建议
在HomeFragment的提交按钮点击事件中,未判断热量输入是否为有效数字,可能触发NumberFormatException,建议添加校验:
binding.bSubmit.setOnClickListener{ val foodTitle= binding.etName.text.toString().trim() val foodCaloriesStr = binding.etCalories.text.toString().trim() if (foodTitle.isNotEmpty() && foodCaloriesStr.isNotEmpty()){ try { val foodCalories = foodCaloriesStr.toInt() val food= food(foodTitle, foodCalories, false ) foodlistadapter.addFood(food) binding.etName.text.clear() binding.etCalories.text.clear() } catch (e: NumberFormatException) { // 可在此提示用户输入有效的数字 } } }
内容的提问来源于stack exchange,提问作者Wzyl
相关产品推荐
相关产品推荐

