【发布时间】:2021-01-05 10:54:46
【问题描述】:
背景
我将我的应用设置为六边形架构,将 UI(应用)、域和数据库(房间)作为单独的模块。按下 UI 中的按钮后,用户输入数据将保存在房间数据库中。如果 Room 数据库抛出 SQLiteConstraintException 表示该键已存在于数据库中,我想查询用户是否覆盖数据。
我的想法
我是 android/kotlin 开发的新手,但我想这是如何工作的,我会有一个触发 UI AlertDialog 的事件。我将在 DB 模块中引发此事件,如果接受警报对话框,则回调将在我的 Room DAO 中运行 save 方法,这将覆盖数据。
问题
- 我试图在 Kotlin 中查找一些有关事件的文档,但没有找到。也许我没有使用正确的术语,但“事件”在 Kotlin 中似乎不是一个公认的东西。
- DB 模块看不到 UI 模块,因此无法直接从 DB 创建对话框。这就是我想首先使用事件的原因。
- 因为 Room 是异步的,我在
Dispatchers.IO协程中运行 save 方法,据我所知,它不可能在 IO 协程中创建 UI 片段(如对话框)。到目前为止,我已经通过使用this@MyActivity.runOnUiThread绕过了这个问题,但这感觉很hacky。
我的尝试
GlobalScope.launch(Dispatchers.IO) {
val result = data.save(force = false)
when (result) {
false -> {
this@DataSaverActivity.runOnUiThread {
GenericDialogs(this@DataSaverActivity)
.confirmDialog(
onAccept = {data.save(force = true)},
onReject = {println("dialog rejected")})
}
}
true -> println("Successfully saved")
}
}
这是我的第一次尝试,确实有效,但我对此一点也不满意。此代码在我的视图模型中的一个方法中,当按下保存按钮时调用该方法。
如果 Dao 引发 SQLiteConstraintException,data.save() 返回 false,否则返回 true。 force 参数确定是使用onConflict = ABORT 还是onClonflict = REPLACE 保存数据。基本上,如果force 为真,它将覆盖预先存在的键,如果为假,它将抛出 SQL 错误。保存失败时,将创建一个对话框并提供一个回调,该回调通过强制覆盖重新保存。
我更喜欢在 Kotlin 中使用事件或类似的东西来清理逻辑。
【问题讨论】:
标签: android kotlin kotlin-coroutines hexagonal-architecture