こちらと同様のことを行いました。
[Kotlin]Roomを用いたデータベース操作
プロジェクトの作成
プロジェクト名: Room01
環境
build.gradle.kts_Project_Room01
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.android.application") version "8.1.2" apply false
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
id("com.google.devtools.ksp") version "1.9.20-1.0.14" apply false
}
build.gradle.kts_Module_app
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("com.google.devtools.ksp")
}
(省略)
android {
(省略)
buildFeatures {
viewBinding = true
}
}
dependencies {
val room_version = "2.6.0"
//Room
implementation("androidx.room:room-runtime:$room_version")
ksp("androidx.room:room-compiler:$room_version")
implementation("androidx.room:room-rxjava2:$room_version")
implementation("androidx.room:room-rxjava3:$room_version")
implementation("androidx.room:room-guava:$room_version")
testImplementation("androidx.room:room-testing:$room_version")
implementation("androidx.room:room-paging:$room_version")
// kotlin coroutines 非同期、メインスレッド処理用
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3")
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.10.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
}
画面
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="64dp"
android:paddingHorizontal="16dp"
android:text="Hello World!" />
<Button
android:id="@+id/addButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="32dp"
android:text="データ追加" />
<Button
android:id="@+id/displayButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="32dp"
android:text="データ表示" />
</LinearLayout>
プログラム
MainActivity.kt
package com.example.room01
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.room.Room
import com.example.room01.databinding.ActivityMainBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.textView.text = "こんにちは"
val database = Room.databaseBuilder(
this, RoomSampleDatabase::class.java, "room_sample_database.db")
.fallbackToDestructiveMigration()
.build()
val notificationDao = database.notificationDao()
binding.addButton.setOnClickListener {
GlobalScope.launch(Dispatchers.IO) { // 非同期処理
val lastId = notificationDao.selectLastId()
val state = NotificationState(lastId + 1, "いいねをもらいました\n")
notificationDao.insert(state)
GlobalScope.launch(Dispatchers.Main) { // main thread
Toast.makeText(this@MainActivity, "データ追加しました", Toast.LENGTH_SHORT).show()
}
}
}
binding.displayButton.setOnClickListener {
GlobalScope.launch(Dispatchers.IO) { // 非同期処理
val states = notificationDao.selectAll()
GlobalScope.launch(Dispatchers.Main) { // main thread
binding.textView.text = states.toString()
}
}
}
}
}
NotificationDao.kt
package com.example.room01
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
@Dao
interface NotificationDao {
// アイテム追加
// onConflict = OnConflictStrategy.REPLACE しておくとデータが重複した場合でも自動でupdateにしてくれる insertといいつつupsertです
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(state: NotificationState)
// 複数のアイテム追加
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(states: List<NotificationState>)
// idを指定して取得
@Query("SELECT * FROM notification WHERE id = :id LIMIT 1")
fun select(id: String): NotificationState
// 最後のid取得
@Query("SELECT id FROM notification ORDER BY id DESC LIMIT 1")
fun selectLastId(): Int
// 全てのアイテム取得
@Query("SELECT * FROM notification")
fun selectAll(): List<NotificationState>
// 全てのアイテム取得 LiveData
@Query("SELECT * FROM notification")
fun selectAllWithLiveData(): LiveData<List<NotificationState>>
// データを全て削除
@Query("DELETE FROM notification")
fun deleteAll()
}
NotificationState.kt
package com.example.room01
import androidx.room.ColumnInfo
import androidx.room.Entity
@Entity(
tableName = "notification",
primaryKeys = ["id"]
)
data class NotificationState(
@ColumnInfo(name = "id") val id: Int = 0,
@ColumnInfo(name = "message") val message: String
)
RoomSampleDatabase.kt
package com.example.room01
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
@Database(
entities = [NotificationState::class],
version = 1
)
@TypeConverters
abstract class RoomSampleDatabase : RoomDatabase() {
abstract fun notificationDao(): NotificationDao
}
実行結果
Terminal でデータの確認
adb -s emulator-5554 shell
$ adb -s emulator-5554 shell
emu64xa:/ $ run-as com.example.room01
emu64xa:/data/user/0/com.example.room01 $ ls
cache code_cache databases files
emu64xa:/data/user/0/com.example.room01 $ ls databases
room_sample_database.db room_sample_database.db-wal
room_sample_database.db-shm
qlite3 databases/room_sample_database.db <
SQLite version 3.39.2 2022-07-21 15:24:47
Enter ".help" for usage hints.
sqlite> .table
android_metadata notification room_master_table
sqlite> select * from notification;
1|いいねをもらいました
2|いいねをもらいました
3|いいねをもらいました
4|いいねをもらいました
5|いいねをもらいました
sqlite>.quit