我正在用 Kotlin 编写我的第一个应用程序,所以我对此很陌生。它执行的功能之一是从 API 读取内容,然后根据结果更新屏幕。
我已经用协程尝试了很多东西,但似乎没有任何效果。
例如,我有这样的事情:
private fun readAPI() {
runBlocking {
fun rAPI() = async {
val api = "..."
result = URL(api).readText()
}
println(tag, "Result: " + rAPI().await())
}
}
Run Code Online (Sandbox Code Playgroud)
以及许多不同的方法。似乎没有任何效果。在上述情况下,我收到异常“android.os.NetworkOnMainThreadException”。
到目前为止唯一有效的方法是使用 OkHttp3,如下所述:https ://rstopup.com/como-hacer-una-solicitud-a-la-api-de-kotlin.html (它是西班牙语,但是你会明白的),这很有效,它带来了 API 响应,我解析它,填充我的 sqlite3 数据库等等。但是,由于我不知道 API 何时结束,因此无法更新屏幕控件。如果我尝试连续进行,我会得到一个例外,即只有启动活动的线程才能更新活动或类似的东西。
我已经看到并遵循了很多关于挂起函数、启动等的教程,他们试图用 模仿 API 调用delay(),这些教程工作得很好,直到我尝试进行真正的 API 调用。
那么,您能否指出一个完整的示例,说明如何使用 Kotlin 调用 API,然后更新一些屏幕元素?
编辑我正在编辑通过 val 改变乐趣:
runBlocking {
val rAPI = async {
val api = "..."
URL(api).readText()
}
Log.w(tag, rAPI.await())
}
Run Code Online (Sandbox Code Playgroud)
我得到了“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()
}
Run Code Online (Sandbox Code Playgroud)
结果日志
09:36:09.500 D/: #runs on DefaultDispatcher-worker-1
// 10 seconds later
09:36:19.678 D/: #runs on main
Run Code Online (Sandbox Code Playgroud)
我认为这应该可以解决问题。
不过,我建议您通过将回调(带有 onSuccess 和 onFail 或其他内容)传递给其中来了解如何使用 OkHttp/Volley。或者Retrofit2用来RxJava处理许多这样的问题。
编辑
对于Module with the Main dispatcher had failed to initialize错误,withContext()将此行替换为
withContext(Handler(Looper.getMainLooper()).asCoroutineDispatcher())
Run Code Online (Sandbox Code Playgroud)
编辑 现在不要使用RxJava,使用liveData/LiveEvent来实现观察者模式
| 归档时间: |
|
| 查看次数: |
12754 次 |
| 最近记录: |