kotlin - 协程崩溃
问题描述
我的功能很简单,
主线程:初始化一个变量->
后台线程:触发网络请求,将结果分配回上一个变量 ->
主线程:显示该变量
下面的代码:
suspend fun createCity(context: Context, newCity: MutableLiveData<NewIdea>, mapBody: Map<String, String>, token: String) {
lateinit var response: NewIdea
try {
withContext(Dispatchers.IO) {
val map = generateRequestBody(mapBody)
response = webservice.createIdea(tripId, map, "Bearer $token")
getTrip(context, token)
}
} catch (e: Exception) {
Log.e(TAG, e.message)
}
newCity.value = response
}
但有时(实际上只发生了 2 次)crashlytics 报告这条线的崩溃newCity.value = response
Fatal Exception: kotlin.UninitializedPropertyAccessException: lateinit property response has not been initialized
我真的不明白这怎么会发生。这是从协程函数返回值的正确方法吗?
谢谢
解决方案
好吧,如果 try 块失败,则可能根本没有设置 lateinit 变量。您也应该将 ui 更新代码放在 try 块中,并Exception
单独处理:
旁注: withContext 已针对返回值进行了很好的优化,因此您可以使用它。
suspend fun createCity(context: Context, newCity: MutableLiveData<NewIdea>, mapBody: Map<String, String>, token: String) {
try {
val response: NewIdea = withContext(Dispatchers.IO) {
val map = generateRequestBody(mapBody)
// does createIdea() first store it in var, then does getTrip(), then returns the result of createIdea() stored previously
webservice.createIdea(tripId, map, "Bearer $token").also { getTrip(context, token) } // ^withContext
}
newCity.value = response
} catch (e: Exception) {
Log.e(TAG, e.message)
}
}
一个快速提示(可选):您可以使用 withContext 包装 UI 更新代码,当不在主线程中运行时将工作分派到 Dispatchers.Main,而如果在 main 中运行则什么也不做:
withContext(Dispatchers.Main.immediate) {
val response: NewIdea = withContext(Dispatchers.IO) {
val map = generateRequestBody(mapBody)
// does createIdea() first store it in var, then does getTrip(), then returns the result of createIdea() stored previously
webservice.createIdea(tripId, map, "Bearer $token").also { getTrip(context, token) } // ^withContext
}
newCity.value = response
}
推荐阅读
- keras - 在 Keras 中,有没有类似于 Pytorch 中的 zero_grad() 的函数?
- android - 片段不通过 sharedViewModel 和 LiveData 进行通信
- glassfish - Glassfish 错误起始域。不支持认可的目录
- java - 如何将 java LocalDateTime 转换为 DolphinDB 时间戳?
- apache-kafka - Apache Kafka 中面向消费者的静态成员资格
- java - 如何通过 getName().endsWith() 使用 FileFilter 的方法参考
- c++ - 在函数内部的声明中初始化一个数组并在外部使用它
- javascript - 如何使用javascript递归更新嵌套数组
- ios - Swift:推送视图控制器后,导航栏后面的 UISearchController 错误内容
- java - 将两个给定数组配对并赢得大部分比较的最佳策略