バックグラウンド
UI (アプリ)、ドメイン、およびデータベース (ルーム) を個別のモジュールとして、六角形のアーキテクチャとしてアプリをセットアップしています。UI のボタンを押すと、ユーザー入力データがルーム データベースに保存されます。Room データベースがSQLiteConstraintException
キーが DB に既に存在するという意味をスローする場合、データを上書きするかどうかをユーザーに問い合わせたいと思います。
私のアイデア
私はアンドロイド/コトリン開発に不慣れですが、これがどのように機能すると想像するかは、UIアラートダイアログをトリガーするイベントがあることです。DB モジュールでこのイベントを発生させ、アラート ダイアログが受け入れられた場合、コールバックが Room DAO で save メソッドを実行し、データを上書きします。
問題点
- Kotlin のイベントに関するドキュメントをいくつか見つけようとしましたが、何もありませんでした。正しい用語を使用していない可能性がありますが、「イベント」は Kotlin では認識されていないようです。
- DB モジュールは UI モジュールを認識しないため、ダイアログを DB から直接作成することはできません。これが、そもそもイベントを使用したい理由です。
- Room は非同期であるため、保存メソッドを
Dispatchers.IO
コルーチンで実行しています。私の知る限り、IO コルーチンで UI フラグメント (ダイアログなど) を作成することはできません。これまでのところ、使用してこの問題を回避してきましthis@MyActivity.runOnUiThread
たが、それは非常にハッキリしています。
私が試したこと
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")
}
}
それで、最初の試みの私のハックジョブはうまくいきますが、まったく満足していません。このコードは、保存ボタンが押されたときに呼び出されるビューモデルのメソッドにあります。
data.save()
Dao が a を上げる場合は false を返し、それ以外の場合はSQLiteConstraintException
true を返します。引数は、またはforce
を使用してデータを保存するかどうかを決定します。基本的に true の場合は既存のキーを上書きし、false の場合は SQL エラーをスローします。保存に失敗すると、ダイアログが作成され、強制的に上書きして再保存するコールバックが提供されます。onConflict = ABORT
onClonflict = REPLACE
force
ロジックをクリーンアップするために、Kotlin でイベントまたは同等のものを使用することをお勧めします。