Android待办App崩溃 Logcat提示todoAdapter lateinit属性未初始化
崩溃原因
报错lateinit property todoAdapter has not been initialized的直接原因是:你用lateinit关键字声明了todoAdapter变量,但在第一次访问这个变量(给rvTodoItems.adapter赋值、点击事件里调用todoAdapter.addTodo、删除按钮调用todoAdapter.deleteDoneTodos)之前,从来没有给这个变量赋过有效值。Kotlin的lateinit属性不允许访问未初始化的实例,直接访问就会抛出这个运行时崩溃。
删除lateinit声明后App不崩溃,但RecyclerView无法加载条目,是因为你根本没有给RecyclerView设置合法的Adapter实例,RecyclerView没有绑定数据适配器自然无法渲染条目。
另外你代码里声明的todoViewModel同样是lateinit属性且没有初始化,就算修了adapter的问题,执行插库逻辑时也会触发同样的lateinit未初始化崩溃。
修复方案
按以下步骤改代码即可解决:
- 初始化TodoAdapter实例:在
onCreate方法里,给RecyclerView设置adapter之前完成adapter实例化,代码放在setContentView调用之后即可:
- 初始化TodoAdapter实例:在
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 初始化adapter,如果你自定义的TodoAdapter构造需要传参,按实际构造补全 todoAdapter = TodoAdapter() rvTodoItems.layoutManager = LinearLayoutManager(this) rvTodoItems.adapter = todoAdapter // 其余原有逻辑暂时保留 }
- 初始化TodoViewModel实例:ViewModel不能直接new创建,需要通过ViewModelProvider获取,在adapter初始化旁边加以下代码,记得在文件顶部补对应导包:
// 顶部加导包:import androidx.lifecycle.ViewModelProvider todoViewModel = ViewModelProvider(this)[TodoViewModel::class.java]
- 修正新增待办的逻辑bug:你当前的新增逻辑存在执行顺序错误——先清空了输入框内容,再调用
insertDataToDataBase取输入框内容插库,此时输入框内容已经为空,永远插库失败;且重复创建了两次Todo对象,可以直接删掉原insertDataToDataBase方法,把新增按钮的点击逻辑改成:
- 修正新增待办的逻辑bug:你当前的新增逻辑存在执行顺序错误——先清空了输入框内容,再调用
btnAddTodo.setOnClickListener { val todoTitle = etTodoTitle.text.toString().trim() if (todoTitle.isNotEmpty()) { val todo = Todo(0, todoTitle, false) todoViewModel.addTodoToDataBase(todo) todoAdapter.addTodo(todo) etTodoTitle.text.clear() Toast.makeText(this, "Successfully Added", Toast.LENGTH_LONG).show() } else { Toast.makeText(this, "Please fill out all fields", Toast.LENGTH_LONG).show() } }
优化建议
你当前用的
kotlinx.android.synthetic合成控件引用插件已经被Google废弃,建议迁移到ViewBinding,避免控件id匹配错误、空引用等问题。
后续如果要做数据持久化展示,建议给ViewModel中的待办列表数据加生命周期观察,数据变化时自动通知adapter刷新,不要手动在点击事件里调用adapter的add方法,避免UI数据和数据库数据不一致。
内容的提问来源于stack exchange,提问作者Clivityy
相关产品推荐
相关产品推荐

