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

Android使用flowWithLifecycle监听Flow时context空指针问题解决方案

场景

需要加载大量数据后基于这些数据创建UI元素,该操作仅用于测试,问题就出在该环节。

问题

如果使用flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.STARTED),会出现在Fragment不再活跃时(如屏幕旋转、主题切换等场景后)仍收到数据回调的情况,进而触发context空异常。原实现方案不存在该问题。

当前可行方案

以下是运行正常的实现代码:

class MyFragment : Fragment {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // 基于Flow更新UI
        lifecycleScope.launch(Dispatchers.IO) {
            DataManager
                .flowExercises()
                .take(1)
                .collect {
                
                    // 为保证安全,此处检查当前生命周期状态!
                    if (lifecycle.currentState >= Lifecycle.State.STARTED) {
                        val views = it.map {
                            TextView(context).apply {
                                text = it.exercise.name
                                gravity = Gravity.CENTER_HORIZONTAL
                            }
                        }

                        withContext(Dispatchers.Main) {
                            views.forEach {
                                ll.addView(it)
                            }
                        }
                    }
                }
        }
    }
}

不生效的新方案

希望切换到flowWithLifecycle的实现方式,但无法保证运行稳定性,以下是尝试代码:

class MyFragment : Fragment {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // 基于Flow更新UI
        lifecycleScope.launch(Dispatchers.IO) {
            DataManager
                .flowExercises()
                .take(1)
                .flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.STARTED)
                // 映射操作可能耗时较长...
                .map {
                    it.map {
                        TextView(context).apply {
                            text = it.exercise.name
                            gravity = Gravity.CENTER_HORIZONTAL
                        }
                    }
                }
                .collect {
                    withContext(Dispatchers.Main) {
                        views.forEach {
                            ll.addView(it)
                        }
                    }
                }
        }
    }
}

最终可行方案

DataManager
    .flowExercises() // 该操作为IO操作,耗时较长
    .map {
        // 该操作同样耗时,此处仅为测试创建大量视图
        // 每次都检查context,因为该阶段Fragment可能已销毁
        it.map { data ->
            // 如果context不可用,说明Fragment已未挂载
            // => 无需继续创建视图,结果最终也会被丢弃
            // => 是的,这部分工作可能属于无效操作...
            context?.let {
                TextView(it).apply {
                    text = data.exercise.name
                    gravity = Gravity.CENTER_HORIZONTAL
                }
            }
        }
    }
    .flowOn(Dispatchers.IO) // 上述代码运行在IO线程
    .flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.STARTED)
    .onEach { views ->
        // 当前处于STARTED状态,可安全操作UI
        views.forEach {
            ll.addView(it)
        }
    }
    .flowOn(Dispatchers.Main) // 上述代码运行在主线程
    .launchIn(viewLifecycleOwner.lifecycleScope)

内容的提问来源于stack exchange,提问作者prom85

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 22:36:02