JetpackのRoomを使うための設定手順

JetPackのRoomを導入するための手順です。

Gradle

Gradleに追加。

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-kapt' // 追加
}
dependencies {
    // for Room
    implementation "androidx.room:room-runtime:2.4.2"
    kapt "androidx.room:room-compiler:2.4.2"

    implementation 'androidx.core:core-ktx:1.7.0'

エントリーを作成。

Task.kt

import androidx.room.Entity
import androidx.room.PrimaryKey
import java.util.*

@Entity(tableName = "todos")
data class Task (
    @PrimaryKey(autoGenerate = true)
    val id:Int = 0,
    val task:String = "",
    val time:Date = Date(),
    val isDone:Boolean = false
)

Daoを作成。

ToDoDao.kt

import androidx.room.*
import java.util.*

@Dao
interface ToDoDao {
    @Query("select * from todos order by time asc")
    fun getAll(): MutableList<Task>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun post(todo: Task)

    @Delete
    fun delete(todo: Task)
}

class DateTimeConverter {
    @TypeConverter
    fun fromTimestamp(value: Long?): Date? {
        return value?.let { Date(it) }
    }

    @TypeConverter
    fun dateToTimestamp(date: Date?): Long? {
        return date?.time?.toLong()
    }
}

AppDatabase.kt

package com.atmc118.todoapp

import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters

@Database(entities = [Task::class], version = 1, exportSchema = false)
@TypeConverters(DateTimeConverter::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun todoDao(): ToDoDao
}

データベースの作成

RoomSettingApp.kt

package com.atmc118.todoapp

import android.app.Application
import androidx.room.Room

class RoomSettingApp : Application() {
    companion object {
        lateinit var database: AppDatabase
    }

    override fun onCreate() {
        super.onCreate()

        database = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java,
            "todos"
        ).build()
    }
}

起動時に実行されるようにマニフェストファイルに追加。

 <application
        android:name=".RoomSettingApp"

daoを使う

MainActivity.kt

class MainActivity : ComponentActivity() {

    private val dao = RoomSettingApp.database.todoDao()
    private var todoList = mutableStateListOf<Task>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ToDoAppTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    MainScreen(todoList)
                }
            }
        }
        loadTodo()
    }

    @Composable
    fun MainScreen(todoList: SnapshotStateList<Task>) {

        var text: String by remember { mutableStateOf("") }
        val sdf = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")

        Column {
            TopAppBar(
                title = { Text("Todo List") }
            )
            LazyColumn(
                modifier = Modifier
                    .fillMaxWidth()
                    .weight(1f)
            ) {
                items(todoList) { todo ->
                    var checkedState:Boolean by remember { mutableStateOf(false) }
                    Row( modifier = Modifier
                        .fillMaxWidth()
                        .padding(16.dp)
                        .clickable(onClick = { deleteTodo(todo) })) {
                        Checkbox(
                            checked = checkedState,
                            onCheckedChange = {
                                checkedState = it
                            })
                        if(checkedState) {
                            Text(
                                text = todo.task,
                                style = TextStyle(textDecoration = TextDecoration.LineThrough),
                                modifier = Modifier
                                    .padding(16.dp)
                            )
                        }else{
                            Text(
                                text = todo.task,
                                modifier = Modifier
                                    .padding(16.dp))
                        }
                        Text(
                            text = sdf.format(todo.time),
                            color = Color.LightGray,
                            modifier = Modifier
                                .padding(16.dp)
                        )
                    }
                }
            }
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp)
            ) {
                OutlinedTextField(
                    value = text,
                    onValueChange = {text = it},
                    label = { Text("ToDo") },
                    modifier = Modifier
                        .wrapContentHeight()
                        .weight(1f)
                )
                Spacer(Modifier.size(16.dp))
                Button(
                    onClick = {
                        if (text.isEmpty()) return@Button
                        postTodo(text)
                        text = ""
                    },
                    modifier = Modifier.align(Alignment.CenterVertically)
                ) {
                    Text("ADD")
                }
            }
        }
    }

    private fun loadTodo() {
        CoroutineScope(Dispatchers.Main).launch {
            withContext(Dispatchers.Default) {
                dao.getAll().forEach { todo ->
                    todoList.add(todo)
                }
            }
        }
    }

    private fun postTodo(title: String) {
        CoroutineScope(Dispatchers.Main).launch {
            withContext(Dispatchers.Default) {
                dao.post(Task(task = title))

                todoList.clear()
                loadTodo()
            }
        }
    }

    private fun deleteTodo(todo: Task) {
        CoroutineScope(Dispatchers.Main).launch {
            withContext(Dispatchers.Default) {
                dao.delete(todo)

                todoList.clear()
                loadTodo()
            }
        }
    }