lifecycleScope.launch后台失效?exerciseList赋值后仍空指针问题
问题原因分析与解决方案
核心问题1:Flow的collect导致函数无法返回
你的getExerciseListBySetName函数中,处理Constants.MISCELLANEOUS_LIST时用collect监听数据库Flow。Room返回的Flow是持续监听数据变化的冷流,collect会一直挂起不执行后续代码,导致函数永远无法返回ans,最终exerciseList始终为null,调用setUpUiAndExerciseStatusRV时触发空指针异常。
核心问题2:强制非空操作!!放大风险
setUpUiAndExerciseStatusRV中大量使用!!强制解包exerciseList,即便exerciseList被赋值为空列表,当currentExercisePosition超出范围时也会引发异常,空值场景下直接触发空指针。
修复步骤
1. 修正Flow数据获取方式
把collect替换为first(),仅获取数据库当前单次数据,让函数能正常返回:
private suspend fun getExerciseListBySetName(exListName: String): ArrayList<Exercise> { val allExerciseList = Constants.getAllExerciseList() val ans = ArrayList<Exercise>() when (exListName) { Constants.MISCELLANEOUS_LIST -> { val miscellaneousExercisesDao = (application as HelloHealthyApp).miscellaneousExercisesDb.miscellaneousExercisesDao() // 用first()获取单次数据,替代collect持续监听 val dbList = miscellaneousExercisesDao.fetchAllMiscellaneousExercises().first() val list = ArrayList(dbList) for (i in list) { // 增加索引合法性判断,避免越界 val index = i.toInt() if (index in allExerciseList.indices) { ans.add(allExerciseList[index]) } } } else -> { // 保持空列表返回 } } ans.forEach { it.setIsSelected(false) it.setIsCompleted(false) } return ans }
2. 移除强制非空操作,增加空值/空列表判断
修改setUpUiAndExerciseStatusRV,避免!!,提前处理空场景:
private fun setUpUiAndExerciseStatusRV() { val currentList = exerciseList ?: return // 为空则直接返回,终止后续操作 if (currentList.isEmpty()) return // 简化ID字符串拼接逻辑 exercisesArrStr = currentList.joinToString(separator = ",") { it.getId().toString() } // 初始化RecyclerView exerciseRVAdapter = ExerciseStatusAdapter(currentList) binding?.rVExerciseStatus?.apply { layoutManager = LinearLayoutManager(this@ExerciseActivity, LinearLayoutManager.HORIZONTAL, false) adapter = exerciseRVAdapter } exerciseRVAdapter?.notifyDataSetChanged() // 更新当前练习UI,先判断索引合法性 if (currentExercisePosition in currentList.indices) { val currentExercise = currentList[currentExercisePosition] binding?.exerciseImgView?.setImageResource(currentExercise.getImage()) binding?.tVTitle?.text = currentExercise.getName() } binding?.upcomingExerciseTextView?.visibility = View.GONE }
3. 可选:优化变量初始化
将exerciseList初始化为空列表而非null,减少空值判断:
private var exerciseList: ArrayList<Exercise> = ArrayList()
内容的提问来源于stack exchange,提问作者Aditya Jha
相关产品推荐
相关产品推荐

