android - Kotlin android - 将等待结果分配给变量
问题描述
tldr; 如何用异步数据初始化变量
学习 kotlin 和 android,bignerdranch 书中的简单示例。初学者问题在这里。
应用程序上显示一个数据类。
private var characterData = CharacterGenerator.generate()
这里 .generate() 只是得到一个静态元素。(用于显示的其他功能)
我实现了,所以现在点击按钮,数据是从 api 获取的(它有效)
generateButton.setOnClickListener {
GlobalScope.launch(Dispatchers.Main) {
characterData = fetchCharacterData().await()
displayCharacterData()
}
}
问题是如何实现初始数据获取并将其分配给 characterData ?
private var characterData = CharacterGenerator.generate() // we want to replace generate() with the api call results
显然这也行不通
private var characterData = fetchCharacterData().await()
但这也行不通
private var characterData = GlobalScope.launch(Dispatchers.Main) {
characterData = fetchCharacterData().await()
displayCharacterData()
}
那么使用来自 api 的数据分配/初始化 charactedData 的正确方法是什么?
编辑:
fun fetchCharacterData(): Deferred<CharacterGenerator.CharacterData> {
return GlobalScope.async {
val apiData = URL(CHARACTER_DATA_API).readText()
CharacterGenerator.fromApiData(apiData)
}
}
fromApiData 返回 CharacterData 类型的 dataClass 实例
解决方案
既然你不应该阻塞主线程,但字符数据最初是不可用的,你应该从空字符数据开始。我不知道你的字符数据类是什么样的,但你应该以一种允许它为空的方式组合它,或者只允许它为空。您的 UI 代码应该能够处理这种情况,只需不填写数据,或者最初显示 Spinner。
对于任何必须异步获取数据的应用程序,您都会一遍又一遍地看到这种模式。如果它非常快,则无需费心使用微调器。
旁注:避免使用 GlobalScope(文章由 Kotlin 的设计负责人撰写)。
第二个注意事项:有一个返回 Deferred 的函数有点笨拙。协程的标准模式是将其编写为挂起函数,并withContext
在内部使用以确保在从 Main 调度程序调用时不会阻塞:
suspend fun fetchCharacterData(): CharacterGenerator.CharacterData = withContext(Dispatchers.IO) {
val apiData = URL(CHARACTER_DATA_API).readText()
CharacterGenerator.fromApiData(apiData)
}
generateButton.setOnClickListener {
lifecycleScope.launch {
characterData = fetchCharacterData()
displayCharacterData()
}
}
推荐阅读
- 3d - SceneKit:关于定位相机节点的数学问题
- apache-kafka - 分支到多个主题时的 Kafka Streams 架构问题
- c - 连续字符串替换导致 C 中的无效读取
- reactjs - 将 redux observable 与 axios 一起使用
- bash - “非法选项-n”和“[[:未找到”带有答案选项
- bash - 如何创建 bash 脚本来执行一些其他操作
- python - 即使没有数据,如何生成excel文件。Python 熊猫 ExcelWriter
- azure - Azure VMSS - 通过 REST API 扣除正常运行时间
- sql - SQL查询如何删除table2中不活动的表
- java - 如何创建一个循环,反复提示用户输入blast、punch 或kick 进行攻击或Do It!退出循环