Android 协同程序不断崩溃,没有错误显示
我在发展MVP。在我的演示者中,我通过一个挂起函数调用了我的存储库。在这个挂起函数中,我启动了一个协同程序,而不是在主线程上。 当这个协同程序完成时,我想执行一些代码:我正在使用withContext来执行 在我的存储库中,我正在启动一个协同程序,可能我使用DAO在我的房间数据库中插入数据是错误的 当我调试应用程序时,它会进入演示者,但在进入存储库之前会崩溃 演讲者Android 协同程序不断崩溃,没有错误显示,android,kotlin,android-room,androidx,kotlin-coroutines,Android,Kotlin,Android Room,Androidx,Kotlin Coroutines,我在发展MVP。在我的演示者中,我通过一个挂起函数调用了我的存储库。在这个挂起函数中,我启动了一个协同程序,而不是在主线程上。 当这个协同程序完成时,我想执行一些代码:我正在使用withContext来执行 在我的存储库中,我正在启动一个协同程序,可能我使用DAO在我的房间数据库中插入数据是错误的 当我调试应用程序时,它会进入演示者,但在进入存储库之前会崩溃 演讲者 override suspend fun insertUserResponse(activity: Activity, d
override suspend fun insertUserResponse(activity: Activity, data: UserResponse) {
scope.launch(Dispatchers.IO) {
try {
userResponseRepository.insertUserResponse(data)
withContext(Dispatchers.Main) {
redirectToClientMainPage(activity)
}
} catch (error: Exception) {
parentJob.cancel()
Log.e("ERROR PRESENTER", "${error.message}")
}
}
}
存储库
override suspend fun insertUserResponse(userResponse: UserResponse) {
GlobalScope.launch(Dispatchers.IO) {
try {
val existingUser: UserResponse? =
userResponseDAO.searchUserByID(userResponse.profilePOJO.uniqueID)
existingUser?.let {
userResponseDAO.updateUser(userResponse)
} ?: userResponseDAO.insertUser(userResponse)
} catch (error: Exception) {
Log.e("ERROR REPOSITORY", "${error.message}")
}
}
}
我的日志中没有显示错误
编辑:
作用域初始化
private var parentJob: Job = Job()
override val coroutineContext: CoroutineContext
get() = uiContext + parentJob
private val scope = CoroutineScope(coroutineContext)
val uiContext:CoroutineContext=Dispatchers.Main在我的类构造函数中初始化
堆栈跟踪
没有stacktrace很难帮助你 是一篇文章,可能会有帮助。将本文中提到的ViewModel替换为Presenter在您的案例中,您可以在使用协同程序时得到一些一般性建议: 作为一种常规模式,在ViewModel中启动协程,读取:Presenter 我不认为需要在存储库中为您的案例再启动一个协同程序 至于切换房间的协同程序上下文: Room使用自己的dispatcher在后台线程上运行查询。您的代码不应与ContextDispatchers.IO一起使用来调用挂起的房间查询。这将使代码复杂化,并使查询运行变慢 我在官方文件中找不到相同的建议,但在中提到了 房间和改造使悬挂功能主要安全。 从Dispatchers.Main调用这些suspend fun是安全的,即使它们从网络获取并写入数据库 所以您可以在存储库中省略launch和withContext,因为Room保证所有带有suspend的方法都是主安全的。这意味着甚至可以从主线程调用它们。此外,您不能在Presenter中显式定义Dispatchers.IO
还有一件事。如果演示者的insertUserResponse方法是suspend,那么您可以从另一个启动的协同程序调用它,不是吗?在这种情况下,为什么要在这个方法中再启动一个协程呢?或者这个方法不应该挂起?如果没有stacktrace,很难帮助您 是一篇文章,可能会有帮助。将本文中提到的ViewModel替换为Presenter在您的案例中,您可以在使用协同程序时得到一些一般性建议: 作为一种常规模式,在ViewModel中启动协程,读取:Presenter 我不认为需要在存储库中为您的案例再启动一个协同程序 至于切换房间的协同程序上下文: Room使用自己的dispatcher在后台线程上运行查询。您的代码不应与ContextDispatchers.IO一起使用来调用挂起的房间查询。这将使代码复杂化,并使查询运行变慢 我在官方文件中找不到相同的建议,但在中提到了 房间和改造使悬挂功能主要安全。 从Dispatchers.Main调用这些suspend fun是安全的,即使它们从网络获取并写入数据库 所以您可以在存储库中省略launch和withContext,因为Room保证所有带有suspend的方法都是主安全的。这意味着甚至可以从主线程调用它们。此外,您不能在Presenter中显式定义Dispatchers.IO
还有一件事。如果演示者的insertUserResponse方法是suspend,那么您可以从另一个启动的协同程序调用它,不是吗?在这种情况下,为什么要在这个方法中再启动一个协程呢?或者这个方法不应该挂起?我终于找到了答案 感谢@sergiy,我阅读了本文的第二部分,其中提到除了Throwable和CancellationException之外,您无法捕获错误 所以,我没有抓住例外,而是用它换了一次性的。最后,我的日志中显示了一个错误 我正在使用Koin注入我的存储库和所有内容。我在Koin应用程序中缺少androidContext。
就这样。我终于找到了答案 感谢@sergiy,我阅读了本文的第二部分,其中提到除了Throwable和CancellationException之外,您无法捕获错误 所以,我没有抓住例外,而是用它换了一次性的。最后,我的日志中显示了一个错误 我正在使用Koin注入我的存储库和所有内容。我在Koin应用程序中缺少androidContext。
就这样。在存储库中使用withContext更改GlobalScope.launch。作用域是如何初始化的?我尝试了你的解决方案,但仍然崩溃。我已使用存储库中的withContext初始化scope.Change GlobalScope.launch更新了主题。作用域是如何初始化的?我尝试了你的解决方案,但仍然崩溃。我用范围的初始化更新了我的主题。我用堆栈跟踪屏幕编辑了我的初始帖子。我没有
我看不到任何有用的东西,但也许你会的。另外,关于最后一点,我使用了suspend,因为我第一次尝试使用async/await启动协同路由,以便在执行下一行代码之前等待协同路由完成。我后来编辑了我的函数,但忘了删除suspend关键字。如果您注释掉您的try-catch块呢?也许堆栈跟踪中会出现一些东西。我发布了我自己问题的答案。我想非常感谢你分享你的文章,因为我找到了解决方案,感谢它!别忘了接受你自己的答案,因为它解释了问题的真正原因。你要到明天才能回答。谢谢你的提示!我用堆栈跟踪屏幕编辑了我的初始帖子。我没有看到任何有用的东西,但也许你会。另外,关于最后一点,我使用了suspend,因为我第一次尝试使用async/await启动协同路由,以便在执行下一行代码之前等待协同路由完成。我后来编辑了我的函数,但忘了删除suspend关键字。如果您注释掉您的try-catch块呢?也许堆栈跟踪中会出现一些东西。我发布了我自己问题的答案。我想非常感谢你分享你的文章,因为我找到了解决方案,感谢它!别忘了接受你自己的答案,因为它解释了问题的真正原因。你要到明天才能回答。谢谢你的提示!