【Android】KotlinでRoomデータベースを使用

KotlinでRoomデータベースを使用してみたので、覚書。

###関連
続編：
KotlinでRoomデータベースとListViewを繋げてメモ帳を作成
https://qiita.com/clipbord/items/0d8b7f973e3f5b277827

RoomデータベースをListViewで表示するように作成したもの。


####全ソース
https://github.com/CoffCookie/memo

###gradle
Roomとkaptが必要だったため、2つを指定。
最新版は下記

Room:
https://developer.android.com/training/data-storage/room?hl=ja

kapt:
https://kotlinlang.org/docs/reference/kapt.html


私の場合、kaptはversion指定すると上手く行かなかったため、version指定なしで作成している。


```app/build.gradle
plugins {
...
    id 'org.jetbrains.kotlin.kapt'
}

dependencies {
...
    def room_version = "2.2.5"
    implementation "androidx.room:room-runtime:$room_version"
    kapt "androidx.room:room-compiler:$room_version"

    // optional - Kotlin Extensions and Coroutines support for Room
    implementation "androidx.room:room-ktx:$room_version"

    // optional - Test helpers
    testImplementation "androidx.room:room-testing:$room_version"
    implementation "com.google.android.material:material:1.3.0-beta01"
}

```

###データベースのテーブル（フィールド名）を定義


```Memo.kt
...
@Entity
class Memo (
    @PrimaryKey(autoGenerate = true) val id: Int,
    var text: String?
)
```

###データベースにアクセスする際に使用するメソッドを格納

```MemoDao.kt
...
@Dao
interface MemoDao {
    @Query("Select * From memo")
    fun getAll() : List<Memo>

    @Insert
    fun insert(memo: Memo)

    @Update
    fun update(memo: Memo)

    @Delete
    fun delete(memo: Memo)
}
```

###データベースの作成とインスタンスの取得

```MemoDatabase.kt
...
//データベースの作成
@Database(entities = [Memo::class], version = 2)
abstract class MemoDatabase:RoomDatabase() {
    abstract fun memoDao(): MemoDao

    companion object{
        private var INSTANCE: MemoDatabase? = null
        private val lock = Any()

        fun getInstance(context: Context): MemoDatabase{
            synchronized(lock){
                if (INSTANCE == null) {
                    //作成したデータベースのインスタンス取得
                    INSTANCE = Room.databaseBuilder(
                        context.applicationContext,
                        MemoDatabase::class.java, "Memodata.db"
                    )
                        .allowMainThreadQueries()
                        .build()
                }
                return INSTANCE!!
            }
        }
    }
}

```

###View作成
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105573/215d3bb9-0bfb-f775-3e4d-d8fa6f22976f.png" width="25%">



```activity_main.xml
...
    <TextView
        android:id="@+id/memoView"
        android:layout_width="320dp"
        android:layout_height="wrap_content"
        android:text="@string/memo_view"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        tools:layout_editor_absoluteX="43dp"
        tools:layout_editor_absoluteY="64dp" />

    <EditText
        android:id="@+id/memoText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="@string/memo_text"
        app:layout_constraintStart_toStartOf="@+id/memoView"
        app:layout_constraintTop_toBottomOf="@+id/memoView" />

    <Button
        android:id="@+id/saveButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="@string/save_button"
        app:layout_constraintStart_toStartOf="@+id/memoText"
        app:layout_constraintTop_toBottomOf="@+id/memoText" />
...
```

###処理部分の作成
データベースの処理部分に絞って記載したかったため、
表示部分は簡易的に作成している。


```MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //Viewの定義
        val saveButton: Button = findViewById(R.id.saveButton)
        val memoText: TextView = findViewById(R.id.memoText)
        val memoView: TextView = findViewById(R.id.memoView)
        //データベースの定義
        val database = MemoDatabase.getInstance(this)
        val memoDao = database.memoDao()

        //保存ボタン押下時の処理
        saveButton.setOnClickListener{
            //エンティティにデータ設定
            val newMemo = Memo(0,memoText.text.toString())
            //データベースに保存
            memoDao.insert(newMemo)
            //データをQueryで取得して、データベースの最後の要素をmemoViewに出力
            val memoList = memoDao.getAll()
            memoView.text = memoList[memoList.size-1].text


        }
    }
}
```