Be simple

”当たり前”が誰かのためになる

RoomとLiveDataを触ってみた

はじめに

お久しぶりです。

今日はAACの中で、いまだに触っていなかったRoomとLiveDataについて触ってみたのでそれの感想です。でも、LiveDataについてはあまり書いてません。

詳しいところまではまだ理解していないので、DBの確認方法とか、マイグレーションとかについて軽くメモです。

 

Roomとは

Androidの組み込みSQLiteデータベースにアクセスする処理を簡単に記述できるORMラッパーライブラリ。

 公式はこちら

developer.android.com

 

ORMについてはQiitaに概念の記事をまとめてくれている方がいらっしゃったので、引用

qiita.com

 

LiveDataとは

ライフサイクルに応じて、購読解除してくれてデータベースの変更と共にビューに通知してくれるデータオブジェクトを構築してくれる

 

公式リンクはこちら

developer.android.com

 

とりあえず、今回はサンプルを作って試してみました。

サンプルはこちら

github.com

 

ただ、実装は以下の記事を大いに参考にしました!とてもわかりやすかったです。

qiita.com

 

大体のことは上の記事に書かれてあるので、 そちらを参考にしてもらってDBの確認方法と感想を書き残します。

 

DBの確認のためにStethoを利用する

DBの中身を見るのにStethoを用いると良いです。appのbuild.gradleに以下を追加しましょう。

dependencies {
// add Stetho
debugImplementation 'com.facebook.stetho:stetho:1.5.0'
}

開発時だけで良いと思うので、debugImplementationで指定しましょう。

Applicationを継承したクラスのonCreateにてStethoの初期化を行えば、導入完了です。

詳しいStethoに関しては以前記事を書いたので、下記をみてください。

www.rozkey59.tokyo

 

サンプルを動かしてみてDBを確認する

作成したサンプルでは、Userというデータモデルクラスを永続化するようにしています。Userにはidとnameとageを持たせており、Daoクラスにてgetとinsertとdeleteの処理をそれぞれ書いています。

サンプルの画面は次のように作りました。

 

f:id:rozkey59:20190324160917p:plain

サンプル

SAVE、DELETE、 SHOWボタンをそれぞれ配置し、Daoクラスからデータベースの処理を行なっています。

 

今回、Stethoを導入したので、Chromeからデータベースの中身を覗くことができます。

アプリ実行時に、Chromeにてchrome://inspectを入力し、inspectをクリックすると次の画面がみられます。

 

f:id:rozkey59:20190324161522p:plain

Stetho開いた時の画面

赤枠で囲ったResources > Web SQLからDBの中身を確認できます。

Web SQLをクリックすると、サンプルのMainActivityのonCreateの中で、データベースを作成している行で指定している名前が出てくると思います。

自分の場合は、次のようにコードを書きました。

val db = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "User").build()

 Userという名前でDBを作成したので、Stethoで確認すると次のようになります。

f:id:rozkey59:20190324162007p:plain

StethoでDB確認

指定した名前で作られていることが確認できます。

 

それでは、実際にSAVE、DELETE、 SHOWボタンを押してDBに登録、削除、DBから情報を取得するのをやっていきます。

実際の挙動が次の通りになります。

f:id:rozkey59:20190324165347g:plain

挙動確認

DBに登録したり、削除したり、DBに登録してあるnameをTextViewに表示したりをStethoで確認できます。

 

基本的に実装はQiitaの記事のように書けば実現でき、Stethoで中身の確認ができます。

では、マイグレーションはどうでしょうか。

 

マイグレーションについて

DBにカラムを追加したいというときが往往にしてあると思います。

その際にマイグレーションを行う必要があります。Roomの場合についてメモとして残します。

 今回はUserクラスにgenderというカラムを追加してみましょう。

Before

@Entity
class User {

@PrimaryKey
var id: Int = 0

@ColumnInfo(name= "name")
var name: String? = null

var age: Int? = null
}

 

After

@Entity
class User {

@PrimaryKey
var id: Int = 0

@ColumnInfo(name= "name")
var name: String? = null

@ColumnInfo(name= "gender") // 追加
var gender: Int? = null

var age: Int? = null
}

 

次にRoomDatabaseクラスを継承したAppDatabaseクラスでversionをインクリメントします。

Before

@Database(entities = [User::class],  version = 1)
abstract class AppDatabase: RoomDatabase() {
abstract fun userDao(): UserDao
}

 

After

@Database(entities = [User::class],  version = 2) // インクリメント
abstract class AppDatabase: RoomDatabase() {
abstract fun userDao(): UserDao
}

 

インクリメントしないでカラム追加だけ行うと、次のエラーが出ます。

java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number. 

 versionのインクリメントが必須です。

 

次にMigrationを追加します。DBの作成をサンプルではMainActivityのonCreateに記載しているので、そちらに追加します。

Before

val db = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "User").build()

 

After

val db = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "User")
.addMigrations(object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE User ADD gender Int")
}
})
.build()

execSQLで何を変更したか記載します。今回はUserのTableにgenderというカラムを追加し、Int型であることを明記します。

 

これで以前のバージョンのDBがある状態で、ビルドしなおすとマイグレーションできていることが確認できます。

サンプルにて変更前をmasterブランチとし、変更後をfeature/migrateブランチで切ったので、手軽に試すことができるので、サンプルをクローンして試してみてください。

userIdの衝突が起きる可能性があるので、MainActivityのonCreateで次の一文をユニークなものに替えてやるとうまくいきます。

defaultUser.id = Random(1000000).nextInt()

 

先の手順で、Stethoで確認した結果が次の通りです。

f:id:rozkey59:20190324173116p:plain

masterブランチ(変更前)

変更前ではgenderのカラムがないことが上の画像から確認できます。

f:id:rozkey59:20190324173208p:plain

feature/migrateブランチ(変更後)

変更後ではgenderのカラムがあることを上の画像から確認できます。

 

おわりに

RoomとLiveDataは学習コストもそれほどなく、ドキュメントも充実しているので結構簡単にできた感があります。でもユニットテスト書いたりしないといけなかったりなどあるのでもうちょい色々調べていかなくては。。。

 

僕自身DB周りはあまり経験がなかったのですが、簡単に実装できた気がします。特に今の所ははまりどころがなかったです。でも多分プロダクションに当てはめていったり既存の仕組みから移行とかなったら大変そうだなぁ。(しみじみ…)

 

今後多分AACがデフォルトになっていく気がするので引き続き試していこうと思います。