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

Android Kotlin协程报Job was Cancelled导致Spinner为空怎么修复?

根因分析

该偶发问题核心是ShowDatePickerDialog的生命周期和ViewModel、LiveData绑定逻辑错误:

  • ShowDatePickerDialog本质是DialogFragment,用户选中日期触发onDateSet回调后,Dialog会立即销毁。你在Dialog内部通过ViewModelProvider(this)获取的ViewModel绑定的是当前Dialog的生命周期,对应viewModelScope会随着Dialog销毁被主动取消,此时如果网络请求还未完成,就会抛出Job was Cancelled异常。
  • 同时你在Dialog内部对LiveData的观察绑定的是Dialog的生命周期,Dialog销毁后即使请求返回数据,观察者也接收不到回调,自然不会更新Spinner导致空白。

修复方案

必改项

  1. 修正ViewModel实例获取逻辑
    不要在Dialog内部创建绑定自身的ViewModel,改为复用父AddReportFragment的ViewModel,将onDateSet中的代码:
val viewModel = ViewModelProvider(this).get(AddReportViewModel::class.java)

替换为:

val viewModel = ViewModelProvider(requireParentFragment()).get(AddReportViewModel::class.java)

此时ViewModel生命周期和父Fragment绑定,不会随Dialog销毁取消未完成的请求。

  1. 修正LiveData观察的生命周期宿主
    将onDateSet里所有LiveData的observe方法的第一个参数从this(Dialog自身)改为父Fragment的lifecycleOwner,示例如下:
// 修改前
viewModel.mandatoryName.observe(this, Observer { ... })
// 修改后
viewModel.mandatoryName.observe(requireParentFragment().viewLifecycleOwner, Observer { ... })

其余nonMandatoryName、getAll的观察逻辑同理修改,保证Dialog销毁后,父Fragment仍然能正常接收数据回调更新Spinner。

优化项(避免后续隐患)

  • 不要在onDateSet、onItemSelected这类可多次触发的回调里重复注册LiveData观察者,重复注册会导致同一个数据变更触发多次回调。建议把所有LiveData的观察逻辑统一放到AddReportFragment的onCreateView里只注册一次,数据变更自动更新UI。
  • 拆分Dialog职责:DatePickerDialog只负责返回选中的日期,不要在内部处理业务逻辑和UI更新,通过接口回调或者父Fragment的ViewModel把选中的日期抛给AddReportFragment,所有数据请求、UI更新逻辑都在父Fragment内处理,彻底规避生命周期绑定错误的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 20:45:07