如何解决协程不断崩溃而无错误显示
我正在开发MVP。在我的演示者中,由于具有暂停功能,因此可以调用我的存储库。在此暂停功能中,我启动了协程-不在主线程上。 完成此协程后,我想执行一些代码:为此,我正在使用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(在我的类构造函数中初始化)
堆栈跟踪
解决方法
我终于找到答案了!
感谢@sergiy,我阅读了本文的第二部分https://medium.com/androiddevelopers/coroutines-on-android-part-ii-getting-started-3bff117176dd,其中提到您只能捕获Throwable和CancellationException之外的错误。
因此,我没有捕捉到Exception,而是将其交换为Throwable。最后,我的logcat中显示了一个错误。
我正在使用Koin注入我的存储库和所有存储库。我在Koin应用程序中缺少androidContext()。 就是这样。
,没有stacktrace,很难为您提供帮助。
Here是一篇文章,可能会有所帮助。在您的情况下,将本文中提到的ViewModel
替换为Presenter
,您会获得一些使用协程的一般建议:
作为一般模式,请在ViewModel中启动协程(阅读:Presenter)
在您的存储库中,我认为不需要再发布一个协程。
关于为会议室切换协程上下文:
Room使用其自己的调度程序在后台线程上运行查询。您的代码不应使用withContext(Dispatchers.IO)来调用挂起的房间查询。它将使代码复杂化,并使查询运行速度变慢。
我在官方文档中找不到相同的推荐,但是在one of the Google code labs中提到了。
Room和Retrofit都使悬挂功能成为主要安全功能。 从Dispatchers.Main调用这些挂起的乐趣是安全的,即使它们是从网络中获取并写入数据库的。
因此,您可以在存储库中省略launch
(以及withContext
),因为Room保证所有带有suspend
的方法都是主安全的。这意味着即使从主线程也可以调用它们。另外,您无法在Dispatchers.IO
中明确定义Presenter
。
还有一件事。如果Presenter的方法insertUserResponse
被挂起,那么您是从另一个启动的协程调用它的,不是吗?在这种情况下,为什么还要在此方法中启动一个协程?还是不应该使用suspend
这种方法?