如何初始化Kotlin的lateinit属性?解决未初始化异常问题
解决kotlin.UninitializedPropertyAccessException异常:lateinit变量未初始化问题
错误根源
在viewButton的点击事件逻辑中,你犯了异步执行顺序的错误:
- 你声明了
lateinit var student: Student后,通过GlobalScope.launch启动了一个后台协程去查询数据库并给student赋值 - 但协程是异步执行的,主线程会立刻跳过协程,直接执行后面的
val nam = student.name.toString()等代码 - 此时协程里的赋值操作还没完成,
student完全没被初始化,所以抛出lateinit property student has not been initialized异常
修复代码
把访问student属性和页面导航的逻辑全部移到协程内部,并且切换回主线程执行UI相关操作(Android要求UI操作必须在主线程):
binding.viewButton.setOnClickListener { val idzs = binding.zsidRead.text.toString() if (idzs.isNotEmpty()) { // 建议改用viewLifecycleOwner.lifecycleScope替代GlobalScope,避免内存泄漏 viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) { // 在IO线程执行数据库查询 val student = appDb.StudentDao().findByZsid(idzs) // 切换回主线程处理UI和导航 withContext(Dispatchers.Main) { student?.let { val nam = it.name.toString() val gend = it.gender.toString() val schl = it.school.toString() view?.findNavController() ?.navigate(InputFragmentDirections.actionInputFragmentToDataFragment( zsid = idzs, name = nam, gender = gend, school = schl )) } ?: run { Toast.makeText(context, "未找到该学生数据", Toast.LENGTH_SHORT).show() } } } } else { Toast.makeText(context, "请输入查询值!", Toast.LENGTH_SHORT).show() } }
额外优化建议
- 不要用
GlobalScope:它的生命周期不受Fragment管控,容易引发内存泄漏,改用viewLifecycleOwner.lifecycleScope会自动跟随Fragment的生命周期销毁协程 - 增加判空逻辑:数据库查询可能返回null,用
student?.let处理可以避免空指针异常 - 输入校验增强:可以对
idzs的格式做简单验证,比如判断是否为数字等
内容的提问来源于stack exchange,提问作者Dinesh G
相关产品推荐
相关产品推荐

