RoomデータベースとJetpack Composeを使ったローカルデータ管理【Jetpack Compose入門⑬】

Roomデータベースとは?

Roomの概要

Roomは、Googleが提供する公式のデータベースライブラリであり、SQLiteを簡単に扱うための抽象化レイヤーを提供します。Roomを使用することで、SQLの煩雑なコードを簡潔にし、データの管理をより効率的に行えます。

Roomの特徴

  • SQLiteを簡単に利用可能
  • 型安全なデータアクセス
  • LiveDataFlow と統合可能
  • Kotlin Coroutines に対応

本記事では、RoomデータベースをJetpack Composeと連携し、ローカルデータ管理を実現する方法を解説します。

Roomデータベースのセットアップ

依存関係の追加

Roomを利用するには、build.gradle(Module: app)に以下の依存関係を追加します。

dependencies {
    implementation "androidx.room:room-runtime:2.4.3"
    kapt "androidx.room:room-compiler:2.4.3"
    implementation "androidx.room:room-ktx:2.4.3"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"
    implementation "androidx.compose.runtime:runtime-livedata:1.3.0"
}

また、kaptを使用するため、build.gradleに以下を追加してください。

android {
    kapt {
        correctErrorTypes = true
    }
}

Roomデータベースの構成

データモデルの作成

Roomを利用するには、エンティティ(データモデル)を作成する必要があります。

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "notes")
data class Note(
    @PrimaryKey(autoGenerate = true) val id: Int = 0,
    val title: String,
    val content: String
)

DAO(データアクセスオブジェクト)の作成

DAO(Data Access Object)を定義し、データベースへの操作(CRUD)を実装します。

import androidx.room.*
import kotlinx.coroutines.flow.Flow

@Dao
interface NoteDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(note: Note)

    @Update
    suspend fun update(note: Note)

    @Delete
    suspend fun delete(note: Note)

    @Query("SELECT * FROM notes ORDER BY id ASC")
    fun getAllNotes(): Flow<List<Note>>
}

データベースの作成

Roomデータベースを作成し、NoteDao を利用できるようにします。

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase

@Database(entities = [Note::class], version = 1, exportSchema = false)
abstract class NoteDatabase : RoomDatabase() {
    abstract fun noteDao(): NoteDao

    companion object {
        @Volatile
        private var INSTANCE: NoteDatabase? = null

        fun getDatabase(context: Context): NoteDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    NoteDatabase::class.java,
                    "note_database"
                ).build()
                INSTANCE = instance
                instance
            }
        }
    }
}

ViewModelの作成

ViewModelでデータを管理

ViewModelを作成し、データを管理します。

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch

class NoteViewModel(private val noteDao: NoteDao) : ViewModel() {
    val notes: Flow<List<Note>> = noteDao.getAllNotes()

    fun addNote(note: Note) {
        viewModelScope.launch {
            noteDao.insert(note)
        }
    }

    fun deleteNote(note: Note) {
        viewModelScope.launch {
            noteDao.delete(note)
        }
    }
}

Jetpack Composeでデータを表示

Note一覧の表示

取得したデータをJetpack Composeで表示するには、collectAsState() を使用します。

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.lifecycle.viewmodel.compose.viewModel

@Composable
fun NoteScreen(viewModel: NoteViewModel = viewModel()) {
    val notes by viewModel.notes.collectAsState(initial = emptyList())

    Column(modifier = Modifier.fillMaxSize()) {
        LazyColumn {
            items(notes) { note ->
                NoteItem(note, onDelete = { viewModel.deleteNote(note) })
            }
        }
    }
}

個別のノートアイテム

@Composable
fun NoteItem(note: Note, onDelete: () -> Unit) {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(8.dp),
        elevation = 4.dp
    ) {
        Column(modifier = Modifier.padding(16.dp)) {
            Text(text = note.title, fontSize = 20.sp, fontWeight = FontWeight.Bold)
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = note.content, fontSize = 16.sp)
            Spacer(modifier = Modifier.height(8.dp))
            Button(onClick = onDelete) {
                Text("削除")
            }
        }
    }
}

まとめ

  • Roomを使用してローカルデータを管理
  • ViewModelとJetpack Composeを組み合わせて状態管理
  • LazyColumnを活用してデータ一覧を表示

RoomとJetpack Composeを活用することで、ローカルデータを簡単に管理しながら、モダンなUIを構築できます。ぜひ試してみてください!