You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 18:35:41