我有一个协程,我想在启动页面期间在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
}
}
答案 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)
}
}