Roomを使用してローカルデータベースを扱う
以下が参考になるかもです
https://developer.android.com/training/data-storage/room?hl=ja
設定
Project Structure
androidx.room:room-ktxなど最新バージョンを確認してVariablesでroom_versionを追加する
room_version 2.4.3
以下のライブラリをroom_versionで追加
androidx.room:room-ktx
androidx.room:room-runtime
androidx.room:room-compiler
ksp
使用しているKotlinのバージョンにあった設定をする
buildscript {
ext {
room_version = '2.4.3'
}
}
plugins {
id 'com.google.devtools.ksp' version '1.7.20-1.0.7' apply false
}
pluginsにid ‘com.google.devtools.ksp’ を追加
androidx.room:room-compilerのimplementationをkspに変更
plugins {
id 'com.google.devtools.ksp'
}
dependencies {
implementation "androidx.room:room-ktx:$room_version"
implementation "androidx.room:room-runtime:$room_version"
ksp "androidx.room:room-compiler:$room_version"
}
実装
Flow / StateFlow を使用したRoomの実装例です
clickボタンを押すとname = “test_(押した回数)”とnum = ランダム(0-99)がDBに追加されてリストに表示されます
まずDBで使用するテーブルをdata classで、次にDAO(Data Access Object)を作成
RoomDatabaseの定義、DB操作のRepository、ViewModelを作成してます
RoomDatabaseにApplicationContextを渡す必要があるためAndroidViewModelにしています
@Composable fun AppContent(viewModel: MainViewModel = viewModel()) {
val datasList = viewModel.datasList.collectAsState()
var count: Int by rememberSaveable { mutableStateOf( 0) }
MaterialTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Column {
Row(modifier = Modifier.padding(4.dp)) {
Button(onClick = {
val name = "test_${++count}"
if (datasList.value.find { it.name == name } == null) {
viewModel.insert(Datas(name, SecureRandom().nextInt(100)))
}
else {
viewModel.update(Datas(name, SecureRandom().nextInt(100)))
}
}) {
Text("click")
}
Button(onClick = { viewModel.deleteAll() }) {
Text("clear")
}
}
datasList.value?.let { datas ->
LazyColumn {
items(datas) { item ->
Text("${item.name} ${item.num}")
}
}
}
}
}
}
}
@Entity(tableName = "datas_table")
data class Datas(
@PrimaryKey @ColumnInfo(name = "name") var name: String = "",
@ColumnInfo(name = "num") var num: Int = 0,
)
@Dao interface DatasDao {
@Query("SELECT * FROM datas_table ORDER BY name ASC")
fun getAlphabetizedDatasList(): Flow<List<Datas>>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(datas: Datas)
@Update(onConflict = OnConflictStrategy.REPLACE)
suspend fun update(datas: Datas)
@Query("DELETE FROM datas_table")
suspend fun deleteAll()
}
@Database(entities = [Datas::class], version = 1, exportSchema = false)
abstract class DatasRoomDatabase : RoomDatabase() {
abstract fun dao(): DatasDao
companion object {
@Volatile private var INSTANCE: DatasRoomDatabase? = null
fun getDatabase(context: Context): DatasRoomDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
DatasRoomDatabase::class.java,
"app_database"
).build()
INSTANCE = instance
// return instance
instance
}
}
}
}
class DatasRepository(
application: Application,
private val db: DatasRoomDatabase = DatasRoomDatabase.getDatabase(application),
private val dao: DatasDao = db.dao()
) {
val datasList = dao.getAlphabetizedDatasList()
// ワーカースレッド以外で使用した場合警告
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun insert(datas: Datas) {
dao.insert(datas)
}
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun update(datas: Datas) {
dao.update(datas)
}
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun deleteAll() {
dao.deleteAll()
}
}
class MainViewModel(
application: Application
) : AndroidViewModel(application) {
private val repo: DatasRepository = DatasRepository(getApplication())
val datasList: StateFlow<List<Datas>> = repo.datasList.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = listOf()
)
fun insert(datas: Datas) = viewModelScope.launch {
repo.insert(datas)
}
fun update(datas: Datas) = viewModelScope.launch {
repo.update(datas)
}
fun deleteAll() = viewModelScope.launch {
repo.deleteAll()
}
}
Android Studio Dolphin 2021.3.1 Patch 1 built on September 30, 2022