Android 协同程序不断崩溃,没有错误显示

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

我在发展MVP。在我的演示者中,我通过一个挂起函数调用了我的存储库。在这个挂起函数中,我启动了一个协同程序,而不是在主线程上。 当这个协同程序完成时,我想执行一些代码:我正在使用withContext来执行

在我的存储库中,我正在启动一个协同程序,可能我使用DAO在我的房间数据库中插入数据是错误的

当我调试应用程序时,它会进入演示者,但在进入存储库之前会崩溃

演讲者

    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块呢?也许堆栈跟踪中会出现一些东西。我发布了我自己问题的答案。我想非常感谢你分享你的文章,因为我找到了解决方案,感谢它!别忘了接受你自己的答案,因为它解释了问题的真正原因。你要到明天才能回答。谢谢你的提示!