【问题标题】:Cancel coroutine with liveData in Android在 Android 中使用 liveData 取消协程
【发布时间】:2021-05-17 00:41:04
【问题描述】:

我有一个与 Retrofit2、liveData 和 Coroutines 配合使用的应用程序,用于通过我的 API 获取信息。我需要取消工作,如果我们开始新的工作,我尝试使用 Job.cancel(),但出现问题。

这是我的 ViewModel:

class MembersViewModel(private val memberRepository: MemberRepository) : ViewModel() {

    private var job = Job()

    fun getMembers(category: String, year: String) = liveData(job + Dispatchers.IO) {

        emit(Resource.loading(null))

        try {
            val data = memberRepository.getMembers(category, year)
            if (year == "2008") delay(6000)
            if (data.isSuccessful) emit(Resource.success(data)) else emit(Resource.serverError(data))

        } catch (exception: Exception) {
            emit(Resource.error(null, exception.message ?: "Error occurred."))
        }
    }

    fun cancelJob() {
        job.cancel()
    }
}

Fragment,我称之为 ViewModel:

override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {

        setViewModel()
        
        //some code

        binding.membersChipGroup.setOnCheckedChangeListener { chipGroup, chipId ->
            
            //some code

            setObservers(binding, year)
        }

        return binding.root
    }

private fun setViewModel() {
        viewModel = ViewModelProvider(this, ViewModelFactory(ApiHelper(RetrofitBuilder.apiService))).get(MembersViewModel::class.java)
}

private fun setObservers(binding: FragmentOfMembersViewPagerBinding, year: String) {

        viewModel?.cancelJob()

        viewModel?.getMembers(raceType, year)?.observe(viewLifecycleOwner, Observer { resource ->
            when (resource.status) {
                Resource.Status.SUCCESS -> {
                    resource.data?.let { members ->
                        binding.mtv1.text = members.body()?.last().toString()
                    }
                    
                }
                Resource.Status.ERROR -> {
                    //some code
                }
                Resource.Status.LOADING -> {
                    //some code
                }
                Resource.Status.SERVER_ERROR -> {
                    //some code
                }
            }
        })
}

如果我调用viewModel?.cancelJob(),那么viewModel?.getMembers(raceType, year) 不起作用,但如果我删除行viewModel?.cancelJob() 一切正常,但我无法取消viewModel?.getMembers(raceType, year)

【问题讨论】:

  • 你试过用 SupervisorJob() 代替 Job() 吗?
  • @Viktor,是的,同样的事情

标签: android kotlin retrofit2 viewmodel kotlin-coroutines


【解决方案1】:

原因是您在使用之前先取消了JobCoroutine Jobs 一旦变为非活动状态就不应使用,否则它将不起作用。要在ViewModel 中取消现有的Job 后实现这一点,只需创建一个新的instance 并分配它,它将按预期工作

视图模型

fun cancelJob() {
    job.cancel() //instance marked as stale, once cancelled
    job = Job() //new instance will work
}

【讨论】:

  • 如果有时我们在完成的 Job 上使用 cancel() 可以吗?
  • 我想应该没问题,框架会在取消之前检查作业是否处于活动状态。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-03
  • 1970-01-01
  • 2019-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多