wid*_*ayd 9 coroutine kotlin kotlin-coroutines
我正在用 kotlin 学习协程,我有一个问题,进程如何等待进程 1 完成,然后继续处理 2,从下面的示例中,我有一个使用 getNews 访问 API 服务器的对象网络(它运行良好并获取数据)我使用异步等待从refreshNews调用这个getNews,其目的是等待数据然后继续运行,但是“程序不等待”,它只是运行进程2然后进程1完成,所以我无法从API中捕获数据刷新新闻
// process 1 - calling api this running well can get the data see process 2
object Network {
var status : NewsApiStatus = NewsApiStatus.LOADING
private var viewModelJob = Job()
private val coroutineScope = CoroutineScope(viewModelJob + Dispatchers.Main)
fun getNews(filter: String, page: Int =1) : newsData? {
var allNews : newsData? = null
coroutineScope.launch {
RetrofitClient.instance.getAllNews(filter, page).enqueue(object: Callback<newsData>{
override fun onFailure(call: Call<newsData>, t: Throwable) {
status = NewsApiStatus.ERROR
}
override fun onResponse(
call: Call<newsData>,
response: Response<newsData>
) {
status = NewsApiStatus.DONE
var listResult = response.body()
if (listResult != null) {
if (listResult.data.isNotEmpty()) {
allNews = listResult
Timber.tag(TAG).i( "process 1 total allNews = ${allNews!!.data.size}")
}
}
}
})
}
return(allNews)
}
}
// process 2 - calling process 1 with runBlocking
fun refreshNews() = runBlocking{
val newsData = async {
Network.getNews("")
}
Timber.tag(TAG).i("proses 2 ${newsData.await()?.data?.size}")
// here I want newsData to wait until it has data
}
// this main program that call process 2
class NewsListViewModel(application: Application) : AndroidViewModel(application) {
init {
refreshNews()
}
}
Run Code Online (Sandbox Code Playgroud)
launch返回对已启动作业的引用。您可以通过调用它来等待作业完成join():
val job = GlobalScope.launch { // launch a new coroutine and keep a reference to its Job
// ...
}
runBlocking {
job.join() // wait until child coroutine completes
}
Run Code Online (Sandbox Code Playgroud)
目前,您getNews()启动了一个协程并立即返回。 allNews此时尚未初始化。
您需要job.join()在内部调用getNews()(会使其阻塞),或者getNews()如果您想保持异步,则在内部使用 async 并返回其结果(您需要以与 http 客户端不同的方式获取结果,因为您将无法初始化外部声明的变量)。
值得阅读官方协程文档:
| 归档时间: |
|
| 查看次数: |
12643 次 |
| 最近记录: |