我的功能非常简单
主线程:初始化变量->
背景线程:触发网络请求,将结果分配回上一个变量->
主线程:显示该变量
以下代码:
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
}
但是有时候(实际上只发生了两次),crashlytics报告该行newCity.value = response
崩溃了
Fatal Exception: kotlin.UninitializedPropertyAccessException: lateinit property response has not been initialized
我不太了解这种情况如何发生。 这是从协程函数返回值的正确方法吗?
谢谢
答案 0 :(得分:1)
如果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更新代码,该withContext可以将工作分派到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
}