Mokelab Blog

#50 AndroidでToDoアプリを作る - データ定義とデータベース

今回は、ToDoアプリで扱うデータを定義し、データベースを作ってみます。

ToDoアプリで扱うデータ

画面レイアウト案や、ToDoアプリで実現したい機能をもとに、ToDoアプリで扱うデータの定義をしてみましょう。

今回作るToDoアプリは技術習得用アプリなので、「タイトル」と「詳細」をToDoとして保存できるようにしてみます。また、リスト表示もしたいので、作成日時と更新日時も保存しておくとよさそうです。表にすると、ToDoデータは次の定義になります。

項目名 説明
id Int キーとして使う
title String ToDoのタイトル
detail String ToDoの詳細
created Date(Long) ToDoを作った時刻(Unix Timestamp)
modified Date(Long) ToDoを最後に修正した時刻(Unix Timestamp)

「ToDoをサーバーに保存するアプリ」を作る場合、サーバー側の事情もあるのでデータ定義はサーバーサイドエンジニアと協力しながら行うことになるでしょう。

他にToDoアプリで必要となるデータがないか検討してみましょう。サーバーとの連携を行うアプリの場合、ログイン中ユーザーの情報などもデータとして定義しておく必要があります。今回作るToDoアプリは、先ほど定義したToDoの定義だけでよさそうです。

Roomの導入

データの定義ができたので、次はアプリ内にデータベースを作ります。AndroidではSQLiteというリレーショナルデータベースを使うことができます。このSQLiteを簡単に扱うため、Jetpack Roomというライブラリが公式で用意されています。

Roomを使うには、app/build.gradleのdependenciesに次の2行を追加します。バージョンは本記事執筆時点での最新バージョンです。

dependencies {
  implementation 'androidx.room:room-runtime:2.2.5'
  kapt 'androidx.room:room-compiler:2.2.5'
}

kaptを使用しているので、プラグインを追加します。最初から追加されているkotlin-androidより下に記述します。

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

apply plugin: 'kotlin-kapt' //この行を追加 

エンティティを作る

(ここから先の説明は、過去記事の繰り返しになります)

まず、テーブルの1行分のデータを表すクラスを作ります。このようなクラスをエンティティと呼びます。先ほどのデータ定義に従って、ToDoクラスを追加しましょう。model/todoパッケージを作り、その中にいれておくとよいでしょう。

package com.mokelab.mytodo.model.todo

import androidx.room.Entity
import androidx.room.PrimaryKey
  
@Entity
data class ToDo(
  @PrimaryKey(autoGenerate = true)
  val _id: Int = 0,
  val title: String,
  val detail: String,
  val created: Long,
  val modified: Long
)

クラスに対し、@Entityをつけると、Roomは対応するテーブルを自動で作ってくれます。また、各プロパティがテーブルの列になります。@PrimaryKeyをつけるとその列が主キーになります。今回はIDを主キーにしたいので、_idプロパティに@PrimaryKeyを付けます。

DAOを作る

次に、ToDoテーブルを操作するためのDAO(Data Access Object)定義を作ります。Roomでは次のようにインターフェースで定義します。

package com.mokelab.mytodo.model.todo

import androidx.room.*
import kotlinx.coroutines.flow.Flow
  
@Dao
interface ToDoDAO {
  @Query("select * from ToDo where created < :startCreated order by created desc limit :limit")
  fun getWithCreated(startCreated: Long, limit: Int): Flow<List<ToDo>>
  
  @Insert
  suspend fun create(todo: ToDo)
  
  @Update
  suspend fun update(todo: ToDo)
  
  @Delete
  suspend fun delete(todo: ToDo)
}

追加・更新・削除は、引数にToDoを受け取るメソッドを定義し、対応するアノテーションを付けます。データの取得は、@Queryアノテーションの中にSQLを書きます。今回は、「作成日時が指定したもの未満で、上位n件を取ってくる」ものにしてみました。 SQL中の:で始まるパラメータ(今回はstartCreatedlimit)は、メソッドの引数で渡された値に置き換えられて実行されます。戻り値の型をKotlinコルーチンのFlow<T>にすることで、データベースの監視機能がつきます。

データベースを作る

SQLiteではデータベースをファイルで保存しています。 1つのデータベースには複数のテーブルが入っているので、どのテーブルが入っているかを記述してあげる必要があります。 Roomでは次のような抽象クラスを定義します。

package com.mokelab.mytodo.model.todo

import androidx.room.Database
import androidx.room.RoomDatabase
  
@Database(entities = [ToDo::class], version = 1)
abstract class ToDoDatabase: RoomDatabase() {
  abstract fun todoDAO(): ToDoDAO
}

RoomDatabaseを継承したクラスを作ります。そして@Databaseアノテーションを付けます。 アノテーションの引数には、ファイルにどのテーブル(エンティティ)を含めるかをentitiesで指定し、データベースのバージョンを versionで指定します。

まとめ

ToDoアプリで使うデータの定義と、Roomを使ったデータベース作成までをやってみました。データ定義は一度アプリをリリースすると、あとから変更するのに手間がかかります。必要な項目は何か、よく検討しながら行いましょう。

本サイトではサービス向上のため、Google Analyticsを導入しています。分析にはCookieを利用しています。