Android Kotlin:如何执行异步函数并等待它完成?
我正在Kotlin编写我的第一个应用程序,所以我对这个很陌生。它执行的功能之一是从API中读取一些内容,然后根据结果更新屏幕 我已经尝试了很多关于协同程序的事情,但似乎什么都不起作用 例如,我有这样的东西:Android Kotlin:如何执行异步函数并等待它完成?,android,kotlin,Android,Kotlin,我正在Kotlin编写我的第一个应用程序,所以我对这个很陌生。它执行的功能之一是从API中读取一些内容,然后根据结果更新屏幕 我已经尝试了很多关于协同程序的事情,但似乎什么都不起作用 例如,我有这样的东西: private fun readAPI() { runBlocking { fun rAPI() = async { val api = "..." result = URL(api).readText()
private fun readAPI() {
runBlocking {
fun rAPI() = async {
val api = "..."
result = URL(api).readText()
}
println(tag, "Result: " + rAPI().await())
}
}
还有很多不同的方法。似乎什么都不管用。在上面的例子中,我得到一个异常“android.os.NetworkOnMainThreadException”
到目前为止,唯一有效的方法是使用OkHttp3,如下所述:(它是西班牙语的,但你会明白的),这很有效,它带来了API响应,我解析它,填充我的sqlite3数据库,等等。但是,由于我不知道API何时结束,所以无法更新屏幕控件。如果我尝试按顺序执行,我会得到一个例外,即只有启动活动的线程才能更新活动或类似的内容
我看过很多关于挂起函数、启动等的教程,并遵循这些教程,他们尝试使用delay()
模拟API调用,这些教程工作得非常好,直到我尝试执行真正的API调用为止
那么,您能给我举一个完整的例子,说明如何使用Kotlin调用API,然后更新一些屏幕元素吗
编辑
我正在编辑val的《改变乐趣》:
runBlocking {
val rAPI = async {
val api = "..."
URL(api).readText()
}
Log.w(tag, rAPI.await())
}
我得到了“android.os.NetworkOnMainThreadException”异常。既然您想使用
coroutine
-async
方式,您必须告诉主线程等待您。您需要使用suspend
函数或块来执行此操作
GlobalScope.launch {
suspend {
Log.d("coroutineScope", "#runs on ${Thread.currentThread().name}")
delay(10000)
withContext(Dispatchers.Main) {
Log.d("coroutineScope", "#runs on ${Thread.currentThread().name}")
}
}.invoke()
}
结果日志
09:36:09.500 D/: #runs on DefaultDispatcher-worker-1
// 10 seconds later
09:36:19.678 D/: #runs on main
我认为这应该能奏效
不过,我建议您通过将回调(onSuccess和onFail等)传递到OkHttp/Volley中来理解如何使用OkHttp/Volley。
或者使用RxJava
对2
进行改造,以处理其中许多问题
编辑
对于带有主调度器的模块未能初始化错误,请将替换为context()
行
withContext(Handler(Looper.getMainLooper()).asCoroutineDispatcher())
在Kotlin中,您可以按照此codelab中的描述将回调转换为协同路由,而不是runBlocking
tryGlobalScope.launch(Dispatchers.Main)
我也尝试过:(发生了什么?还有-这是什么结果
变量?此时您的异步
任务什么也不返回。为什么要声明fun rApi()
而不是val rApi
?否则,您可以创建一个新线程T,调用API并在内部管理回调,然后用T.join()等待结束。)@Pawel我刚刚编辑了这个问题以向您显示错误我尝试了这个,得到了java.lang.IllegalStateException:缺少带有主调度器的模块。添加提供主调度器的依赖项,例如“kotlinx coroutines android”
尝试通过添加依赖项使用coroutine
“org.jetbrains.kotlinx:kotlinx coroutines core:1.1”
好的,我添加了依赖项(我以为我有),现在我得到了java.lang.IllegalStateException:带有主调度器的模块未能初始化
我有你提到的那个,我必须添加“org.jetbrains.kotlinx:kotlinx coroutines android:1.0.1“
alsoI更新我的答案,可能会解决错误,建议使用最新的coroutines
版本。