Android Room

version情報 #

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt'   <<== 追加kaptはソースコード生成する機能のよう
}


dependencies {
...
    implementation("androidx.room:room-runtime:2.4.1")
    implementation("androidx.room:room-ktx:2.4.1")    <= corutine使うのに必要
    annotationProcessor("androidx.room:room-compiler:2.4.1")
    kapt("androidx.room:room-compiler:2.4.1")

    implementation "androidx.compose.runtime:runtime-livedata:$compose_version"  <= LiveDataをobserveAsState()するのに必要
...
}

https://developer.android.com/jetpack/androidx/releases/room

日本語のページだと古いことがある 英語で見るほうがよさそうです

LiveData #

LiveDataのobserveAsStateを使うには、gradleに以下を追加する

implementation "androidx.compose.runtime:runtime-livedata:$compose_version"

なお、observeAsState()はComposable関数のなかでしか使えない。

ViewModelのなかではLiveDataとして持っておいて、

Composeable関数のなかで、 val state = liveData.observeAsState()として値の変更を監視する

Flowの場合は #

Composableの中で.collectAsStateを使うとステートとして監視できる

Coroutineの使用 #

メインスレッドでQueryできるようにするには、Roomをつくるときに .allowMainThredQueries()を追加する。

    val db = Room.databaseBuilder(
        context,
        KirokuDatabase::class.java, "database.db"
    ).allowMainThreadQueries().build()

insertなどはcorutineを使ってメインスレッド以外で実行するようにする。

コルーチンスコープを作ってDispatchers.IOとするとIO用のスレッドで動作する。

   fun insert(kiroku: Kiroku) {
        val scope = CoroutineScope(Dispatchers.IO)
        scope.launch {
            kirokuDao.insertAll(kiroku)
        }
    }


fun delete(kiroku: Kiroku) {
        val scope = CoroutineScope(Dispatchers.IO)
        scope.launch {
            kirokuDao.delete(kiroku)
        }
    }

Repositoryでsuspendにしてもよい (Daoでsuspendでもよい)

suspend fun insert(kiroku: Kiroku): Int {
    return withContext(Dispatchers.IO) {
        val insertedId = kirokuDao.insert(kiroku)
        insertedId.toInt()
    }
}

これをviewModelスコープから

fun saveEdittingKiroku() {
    viewModelScope.launch(Dispatchers.IO) {
        val insertedID = Graph.repo.insert(kirokuEditting.value)
        Log.d("saveEdittingKiroku", "editID:${kirokuEditting.value.id}, insertedID:$insertedID")
        if (kirokuEditting.value.id == 0 && insertedID != 0) { // newly created
            // copy images from 0 to insertedID
            Graph.repo.moveImageDir(0, insertedID)
        }
    }
}

insertでrowIDを取得する #

返り値をLogにすると、insertした後で自動的に割り当てられたIDが取得できる。

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(kiroku: Kiroku): Long