Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/181.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
Android Kotlin:如何执行异步函数并等待它完成?_Android_Kotlin - Fatal编程技术网

Android Kotlin:如何执行异步函数并等待它完成?

Android Kotlin:如何执行异步函数并等待它完成?,android,kotlin,Android,Kotlin,我正在Kotlin编写我的第一个应用程序,所以我对这个很陌生。它执行的功能之一是从API中读取一些内容,然后根据结果更新屏幕 我已经尝试了很多关于协同程序的事情,但似乎什么都不起作用 例如,我有这样的东西: private fun readAPI() { runBlocking { fun rAPI() = async { val api = "..." result = URL(api).readText()

我正在Kotlin编写我的第一个应用程序,所以我对这个很陌生。它执行的功能之一是从API中读取一些内容,然后根据结果更新屏幕

我已经尝试了很多关于协同程序的事情,但似乎什么都不起作用

例如,我有这样的东西:

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
try
GlobalScope.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
版本。