协程崩溃

时间:2020-07-22 03:00:10

标签: kotlin coroutine

我的功能非常简单

主线程:初始化变量->

背景线程:触发网络请求,将结果分配回上一个变量->

主线程:显示该变量

以下代码:

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

我不太了解这种情况如何发生。 这是从协程函数返回值的正确方法吗?

谢谢

1 个答案:

答案 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
}