0

背景

我将我的应用程序设置为六边形架构,将 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 中使用事件或类似的东西来清理逻辑。

4

1 回答 1

0

我认为这是一个异常处理问题。我会这样做:

  • 按下 UI 中的按钮以保存输入数据,调用用例“saveData”。

  • 在用例中,您捕获 SQL 适配器抛出的基础架构异常,将其转换为自定义业务异常:“DataAlreadyExistsException”,然后将其抛出到 UI。

  • UI 捕获“DataAlreadyExistsException”并对其进行处理,向用户显示要求覆盖数据的对话框。

  • 如果用户按下按钮进行覆盖,将调用另一个用例:“overwriteData”。

  • 如果用户按下不覆盖的按钮,则什么也不做。

于 2021-01-06T03:12:15.977 回答