首页 > 解决方案 > android kotlin CoroutineScope 在一个完全完成后运行另一个

问题描述

我有一个片段,它有两个协程启动功能,一个从网络/数据库中获取数据

另一种是检查房间是否是空的并向用户显示一个弹出窗口。

功能

//this function gets the data
private fun initUI() = launch {

    val data = viewModel.data.await()
    data.observe(this@fragment, Observer {
        if (it == null){
            Log.d(TAG, "initui observer is null")
            return@Observer
        }
            adapter = StoreAdapter(it, activity.baseContext)
            recyclerView.adapter = adapter
            activity.progressDisplay()
    })
    checkData().join()
}

//this function is designed to go after initUI()
private fun checkData() = launch {
    delay(3000L) //temp solution
    val check = viewModel.check.await()
    Log.d(TAG, "$check")
    if(check == 0L){
        activity.showPopup(getString(R.string.error_text), getString(R.string.data_error), retry = true)
    }
}

如果我只是 checkData().join() 如果数据库中没有数据开始,它会给我我的弹出窗口,然后在它之后工作正常。所以我增加了 3 秒的延迟,但是我不喜欢这种方式,但不确定是否还有其他方式?

@编辑

视图模型只是做一个 Lazy Defered 调用我的存储库

回购初始化

init {
    source.downloadedData.observeForever { data->
        saveData(data)
    }
}

viewmodel.data 存储库代码

override suspend fun getData(): LiveData<List<item>> {
    return withContext(Dispatchers.IO) {
        initJsonData()
        return@withContext myDao.getAll()
    }
}

initJsonData 是一个检查日期函数,如果为 true,则从网络返回数据。

一旦我们创建了 init repo,我们就会永远观察来自网络的数据,并根据需要将其保存到房间 dB。

视图模型检查代码 在某种程度上遵循与获取数据相同的逻辑,但我只是从房间表中进行选择计数并返回结果。

  override suspend fun checkData(): Long {
    return withContext(Dispatchers.IO) {
        Log.i(TAG, "checkData")
        isDataEmpty()
    }
}

标签: androidkotlinkotlin-coroutines

解决方案


您有一个Observer永远在观察下载的数据,当它观察到数据时,它会继续将其保存在您的数据库中。但是请记住,这并不能保证在saveData(data)获取数据的代码之后立即调用此观察者(即)内部的代码,所以让我们将其分解如下:

  1. 当您调用initUI()方法时,第一行代码会获取数据并等待数据仅被获取而不是等待它被保存

  2. 在那之后,你checkData()和你saveData(data)将竞相同时执行他们的逻辑。可悲的是,在saveData()将任何内容保存在数据库中之前,checkData()将错误返回给您。

一种解决方案是saveData()在您获取它之后并在调用checkData().join()同一个协程之前,如下所示:

private fun initUI() = launch {
    val data = viewModel.data.await()

    //Some other codes...

    saveData(data.value) //If it's an asynchronous function, await for it.


    checkData().join()    
}

请注意,如果saveData(data)是异步的,你必须await为它。


推荐阅读