协程不断崩溃而不显示错误
Posted
技术标签:
【中文标题】协程不断崩溃而不显示错误【英文标题】:Coroutine keeps crashing without showing error 【发布时间】:2021-01-29 02:48:40 【问题描述】:我正在开发 MVP。在我的 Presenter 中,由于挂起功能,我调用了我的存储库。在这个挂起函数中,我启动了一个协程——而不是在主线程上。 当这个协程完成后,我想执行一些代码:我正在使用 withContext() 来执行此操作。
在我的存储库中,我正在启动一个协程(也许我错了)以使用 DAO 将我的数据插入到我的 Room 数据库中。
当我调试我的应用程序时,它会进入我的 Presenter,但在进入我的存储库之前会崩溃。
演讲者
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")
我的 logcat 中没有显示错误。
编辑:
作用域初始化
private var parentJob: Job = Job()
override val coroutineContext: CoroutineContext
get() = uiContext + parentJob
private val scope = CoroutineScope(coroutineContext)
val uiContext: CoroutineContext = Dispatchers.Main(在我的类构造函数中初始化)
堆栈跟踪
【问题讨论】:
在存储库中将GlobalScope.launch
更改为 withContext
。以及scope
是如何初始化的?
我尝试了您的解决方案,但它仍然崩溃。我已经用作用域的初始化更新了我的主题。
【参考方案1】:
我终于找到了答案!
感谢@sergiy,我阅读了这篇文章的第二部分https://medium.com/androiddevelopers/coroutines-on-android-part-ii-getting-started-3bff117176dd,其中提到除了 Throwable 和 CancellationException 之外,您无法捕获错误。
因此,我没有捕获 Exception,而是将其换成了 Throwable。最后,我的 logcat 中显示了一个错误。
我正在使用 Koin 注入我的存储库和所有内容。我的 Koin 应用程序中缺少我的 androidContext()。 就是这样。
【讨论】:
【参考方案2】:没有堆栈跟踪,很难为您提供帮助。
Here 是一篇文章,可能会有所帮助。在您的情况下,将文章中提到的ViewModel
替换为Presenter
,您可以获得一些使用协程的一般建议:
作为一般模式,在 ViewModel 中启动协程(阅读:Presenter)
我认为不需要在 Repository 中再启动一个协程。
至于切换Room的协程上下文:
Room 使用自己的调度程序在后台线程上运行查询。您的代码不应使用 withContext(Dispatchers.IO) 来调用暂停房间查询。它会使代码复杂化并使您的查询运行速度变慢。
我在官方文档中找不到相同的建议,但在one of the Google code labs 中提到了。
Room 和 Retrofit 都使挂起功能成为主要安全的。 从 Dispatchers.Main 调用这些挂起函数是安全的,即使它们从网络获取并写入数据库。
所以你可以在 Repository 中省略 launch
(以及 withContext
),因为 Room 保证所有带有 suspend
的方法都是主安全的。这意味着它们甚至可以从主线程调用。您也不能在Presenter
中明确定义Dispatchers.IO
。
还有一件事。如果 Presenter 的方法 insertUserResponse
是挂起,那么你从另一个启动的协程调用它,不是吗?在那种情况下,为什么要在这个方法中再启动一个协程呢?或者这个方法不应该是suspend
?
【讨论】:
我用我的堆栈跟踪屏幕编辑了我的初始帖子。我没有看到任何有用的东西,但也许你会。另外,关于你的最后一点,我使用了暂停,因为我首先尝试使用 async/await 启动我的协程,以便在执行我的下一行代码(我的重定向)之前等待协程完成。我稍后编辑了我的函数,忘记删除suspend关键字。 如果你注释掉你的 try-catch 块怎么办?也许堆栈跟踪中会出现一些东西。 我发布了我自己问题的答案。我要感谢您(非常感谢)分享您的文章,因为我找到了解决方案! 别忘了接受你自己的答案,因为它解释了问题的真正原因 明天才能做。谢谢你的提示!以上是关于协程不断崩溃而不显示错误的主要内容,如果未能解决你的问题,请参考以下文章
当用户选择一个选项但随后将其更改为另一个选项时,React 崩溃而不显示错误