Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 协调如何等待数据,然后继续处理_Kotlin_Coroutine_Kotlin Coroutines - Fatal编程技术网

Kotlin 协调如何等待数据,然后继续处理

Kotlin 协调如何等待数据,然后继续处理,kotlin,coroutine,kotlin-coroutines,Kotlin,Coroutine,Kotlin Coroutines,我正在学习与kotlin的协同程序,我有一个问题,进程如何等到进程1完成后再继续进程2,从下面的示例中,我有一个对象网络,它使用getNews访问API服务器(运行良好并获取数据) 我使用asynch-await从refreshNews调用了这个getNews,目的是它等待数据,然后继续运行,但“程序不等待”,它只是运行进程2,然后进程1完成,所以我无法在refreshNews中从API捕获数据 // process 1 - calling api this running well can g

我正在学习与kotlin的协同程序,我有一个问题,进程如何等到进程1完成后再继续进程2,从下面的示例中,我有一个对象网络,它使用getNews访问API服务器(运行良好并获取数据) 我使用asynch-await从refreshNews调用了这个getNews,目的是它等待数据,然后继续运行,但“程序不等待”,它只是运行进程2,然后进程1完成,所以我无法在refreshNews中从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()
    }
}
//进程1-调用此运行良好的api可以获取数据,请参阅进程2
对象网络{
变量状态:NewsApiStatus=NewsApiStatus.LOADING
私有变量viewModelJob=Job()
private val coroutineScope=coroutineScope(viewModelJob+Dispatchers.Main)
fun getNews(过滤器:字符串,页面:Int=1):newsData{
var allNews:newsData?=null
协同观测发射{
更新client.instance.getAllNews(过滤器,页面).enqueue(对象:回调{
覆盖失效时的乐趣(调用:调用,t:可丢弃){
status=NewsApiStatus.ERROR
}
覆盖响应(
呼叫:呼叫,,
答复:答复
) {
状态=NewsApiStatus.DONE
var listResult=response.body()
如果(listResult!=null){
if(listResult.data.isNotEmpty()){
allNews=listResult
Timber.tag(tag.i(“进程1总计allNews=${allNews!!.data.size}”)
}
}
}
})
}
返回(所有新闻)
}
}
//进程2-使用runBlocking调用进程1
fun refreshNews()=运行阻塞{
val newsData=async{
Network.getNews(“”)
}
Timber.tag(tag.i(“proses2${newsData.await()?.data?.size}”)
//在这里,我希望newsData等待,直到它有数据
}
//这个主程序调用进程2
类NewsListViewModel(应用程序:应用程序):AndroidViewModel(应用程序){
初始化{
更新新闻()
}
}

launch
返回对已启动作业的引用。通过调用
join()
,您可以使用它来等待作业完成:

val job=GlobalScope.launch{//启动一个新的协同程序并保留对其作业的引用
// ...
}
运行阻塞{
job.join()//等待子协同路由完成
}
当前,您的
getNews()
启动一个协同程序并立即返回<代码>所有新闻此时尚未初始化

您需要在
getNews()
内部调用
job.join()
(这会使其阻塞),或者在
getNews()
内部使用async并返回其结果,如果您想使其保持异步(您需要采用与http客户端不同的结果,因为您无法初始化外部声明的变量)

通过官方的协同程序文档是值得的:


您必须使函数挂起并与上下文{}或异步{}一起使用。wait()谢谢您的提示,它确实帮助我解决了这个问题