背景
我将我的应用程序设置为六边形架构,将 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")
}
}
所以这是我第一次尝试的hackjob,它确实有效,但我对此一点也不满意。此代码在我的视图模型中的一个方法中,当按下保存按钮时调用该方法。
data.save()
如果 Dao 引发 a SQLiteConstraintException
,则返回 false,否则返回 true。该force
参数确定是否使用onConflict = ABORT
或保存数据onClonflict = REPLACE
。基本上如果force
为真,它将覆盖预先存在的键,如果为假,它会抛出 SQL 错误。保存失败时,将创建一个对话框并提供一个回调,该回调通过强制覆盖重新保存。
我更喜欢在 Kotlin 中使用事件或类似的东西来清理逻辑。