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
}
