在协程中的侦听器中等待数据

时间:2018-11-05 20:41:28

标签: android kotlin kotlinx.coroutines

我有一个协程,我想在启动页面期间在android启动时启动。我想等待数据返回,然后再开始下一个活动。做这个的最好方式是什么?目前,我们的android系统正在使用实验性协程0.26.0 ...目前尚无法更改。

更新:我们现在正在使用最新的协程,而不再是实验性的

onResume() {
    loadData()
}

fun loadData() = GlobalScope.launch {
    val job = GlobalScope.async {
        startLibraryCall()
    }
    // TODO await on success
    job.await()
    startActivity(startnewIntent)
}

fun startLibraryCall() {
    val thirdPartyLib() = ThirdPartyLibrary()
    thirdPartyLib.setOnDataListener() { 
        ///psuedocode for success/ fail listeners
        onSuccess -> ///TODO return data
        onFail -> /// TODO return other data
    }
}

2 个答案:

答案 0 :(得分:9)

第一点是,我会将您的loadData函数更改为挂起函数,而不是使用launch。最好可以在呼叫站点定义要如何执行执行的选项。例如,实施测试时,您可能想在runBlocking中调用协程。您还应该正确实现structured concurrency,而不要依赖GlobalScope

在问题的另一方面,我将在ThirdPartyLibrary上实现扩展功能,将其异步调用转换为挂起函数。这样,您将确保调用协程实际上等待Library调用具有一定的价值。

自从我们将loadData设为暂停功能以来,我们现在可以确保仅在ThirdPartyLibrary调用结束时才开始新的活动。

import kotlinx.coroutines.*
import kotlin.coroutines.*

class InitialActivity : AppCompatActivity(), CoroutineScope {
    private lateinit var masterJob: Job
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + masterJob

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        masterJob = Job()
    }

    override fun onDestroy() {
        super.onDestroy()
        masterJob.cancel()
    }

    override fun onResume() {
        this.launch {
            val data = ThirdPartyLibrary().suspendLoadData()
            // TODO: act on data!
            startActivity(startNewIntent)
        }
    }
}

suspend fun ThirdPartyLibrary.suspendLoadData(): Data = suspendCoroutine { cont ->
    setOnDataListener(
            onSuccess = { cont.resume(it) },
            onFail = { cont.resumeWithException(it) }
    )
    startLoadingData()
}

答案 1 :(得分:1)

您可以使用LiveData

liveData.value = job.await()

然后添加例如onCreate()

liveData.observe(currentActivity, observer)

在观察者中,只需等待值不为null,然后开始新的活动

Observer { result ->
            result?.let { 
                startActivity(newActivityIntent)
            } 
}