APIから取得したデータをDBに保存してキャッシュをする場合
Daoの実装
次に、Anime、KeyそれぞれのDaoを順に実装していきます。
AnimeDaoの実装
まずは、Animeのデータを扱うAnimeDaoを実装していきます。
ここで必要になるメソッドは以下になります。
- insertAnime:AnimeクラスのListを引数にとり、DBに保存するメソッドです。
- getAnimePagingSource:AnimeのデータのPagingSourceを返却するメソッドです。戻り値にPagingSource<Int, Anime>のように指定するだけで、「APIから取得したデータを表示するだけ」の際に作成したPagingSourceをRoom側生成してくれるため、大変便利です。
- deleteAllAnime():保存しているアニメをすべて削除するメソッドです。初期読み込みの際にいままで保存した不要になった古いデータを削除するために使用します。
実装したサンプルコードは以下になります。
@Dao interface AnimeDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertAnime(anime: List<Anime>) @Query("SELECT * FROM anime WHERE sessionId = :sessionId") fun getAnimePagingSource(sessionId: String): PagingSource<Int, Anime> @Query("DELETE FROM anime") suspend fun deleteAllAnime() }
PageKeyDaoの実装
次に、RemoteMediatorでデータ取得に使用するpageを保存するためのRemoteKeyDaoを作っていきます。
RemoteMediatorでKeyの値を持つフィールドを定義し、インクリメントするという実装もできますが、DataBaseにsessionIdなどとともに保存した方がより堅実な実装ができるためDBにKeyを保存する手法をとっています。
ここで必要となるメソッドは以下の3つになります。
- insertKey:RemoteKeyを保存するためのメソッドです。RemoteMediatorでKeyを保存する際に使用します。
- getLastKey:同じセッションのidでなおかつ最新のKeyを取得するメソッドです。RemoteMediatorでAPI呼び出しの際のnextKeyを取得するために作成します。
- clearRemoteKey:データベース上に保存されているKeyをすべて削除するメソッドです。初期読み込みの際にいままで保存した不要になった古いKeyを削除するために使用します。
@Dao interface PageKeyDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertKey(key: PageKey) @Query("SELECT * FROM page_key WHERE sessionId = :sessionId ORDER BY id DESC LIMIT 1") suspend fun getLastKey(sessionId: String): PageKey? @Query("DELETE FROM page_key") suspend fun deleteAllPageKey() }
DataBaseの実装
次に、DataBaseを実装していきます。本題ではないため軽く流しますが、TypeConvertersには以前作成したDBにそのまま保存できない型のConverterのクラスを指定します。
次に、entitiesには以前作成したEntityのクラスを指定します。また、Daoを提供する抽象メソッドをそれぞれ定義します。
実装したコードは以下になります。
@TypeConverters(AnimeConverter::class) @Database( entities = [Anime::class, PageKey::class], version = 1, exportSchema = false ) abstract class PagingDataBase : RoomDatabase() { abstract fun getAnimeDao(): AnimeDao abstract fun getPageKeyDao(): PageKeyDao }