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

如何在viewModelScope中从协程返回Long类型值?

解决方案

问题核心在于你试图从viewModelScope.launch中直接返回异步执行的结果,但launch是"fire-and-forget"式的协程启动方式,仅返回Job对象而非任务结果。要获取Long类型的插入ID,只需调整协程的使用方式:

1. 修改ViewModel方法

将createDailyLog改为suspend方法,无需在内部启动新协程,直接调用Repository的挂起方法即可:

class WorkoutListViewModel(
    private val repository: WorkoutListRepository
) : ViewModel() {
    
    ...
    
    @RequiresApi(Build.VERSION_CODES.O)
    suspend fun createDailyLog(part: BodyPart) : Long {
        // 直接返回Repository的挂起方法结果,调用方需在协程中执行此方法
        return repository.createDailyLog(part)
    }
}

2. 在Fragment中调用

Fragment的点击事件不能直接挂起,需使用lifecycleScope启动协程(与Fragment生命周期绑定,自动避免内存泄漏),在协程内部调用ViewModel的挂起方法获取ID:

class WorkoutListTabPagerFragment : Fragment(), WorkoutListAdapter.OnItemClickListener {
   ...
 
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentWorkoutListTabPagerBinding.inflate(inflater, container, false)
        ...
        return binding.root
    }
    
    @RequiresApi(Build.VERSION_CODES.O)
    override fun onItemClick(workout: String) {
        when(PageState.curPageState) {
            is PageState.startWorkout -> {
                // 用lifecycleScope启动协程,默认在主线程执行,可直接更新UI
                lifecycleScope.launch {
                    val id = vm.createDailyLog(part)
                    // 在这里处理拿到ID后的逻辑(如跳转、更新界面等)
                }
            }
            is PageState.addWorkout -> //TODO:
            is PageState.editWorkout -> //TODO:
        }
    }
}

补充说明

  • Room的DAO挂起方法会自动切换到IO线程执行,无需手动指定调度器;
  • lifecycleScope是Jetpack提供的生命周期绑定协程作用域,Fragment销毁时协程会自动取消,避免内存泄漏;
  • 若需在ViewModel中额外处理线程逻辑,可使用withContext(Dispatchers.IO)包裹操作,但此场景下无需额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 23:05:22