はじめに
Paging Libraryを使いたいが既にRepositoryパターンを適用している場合、公式ドキュメントにあるようなDaoの返り値にDataSource.Factory
使うことが難しいケースが多々あるかと思います。
この場合Repositoryをwrapして独自のDataSouceクラスを定義する手法を使うと、既存のRepositoryを活かしつつPaging Libraryを導入することができます。
ここでは以下のようなRepositoryを例にその方法を紹介していきます。
data class User(val id: Long, val name: String, val age: Int)
interface UserRepository {
/**
* [User.age]がageよりも大きく、[User.id]がoffsetIdよりも大きいUserを10件取得します
*/
fun findOlderThan(age: Int, offsetId: Long?) : List<User>
}
DataSourceの構築
DataSourceにはいくつかの抽象クラスが用意されており、データ構造に適したものを選択して使います。
ここではItemKeyedDataSource
を使って構築してみます。
class UserDataSourceFactory(
private val age: Int,
private val userRepository: UserRepository) : ItemKeyedDataSource<Long, User>() {
override fun getKey(item: User): Long = item.id
override fun loadInitial(params: LoadInitialParams<Long>, callback: LoadInitialCallback<User>) {
userRepository.findOlderThan(age, null)
.let { callback.onResult(it) }
}
override fun loadAfter(params: LoadParams<Long>, callback: LoadCallback<User>) {
userRepository.findOlderThan(age, params.key)
.let { callback.onResult(it) }
}
override fun loadBefore(params: LoadParams<Long>, callback: LoadCallback<User>) {
}
}
ItemKeyedDataSource<Key, Value>
のKeyには 取得済みがどこまでか
決定できるパラメータを使います。
ここでは User.id
がその役割を担い Key
にはLong型をあてています。
Value
は取得対象のクラス、ここでは User
がそれにあたります。
DataSourceを使ってみる
独自に構築したDataSourceは以下のように使用します
-
DataSource.Factory<Key, Value>
を継承したクラスでDataSourceを提供する -
LivePagedListBuilder
で1とpaging設定を施してLiveData<PagedList<Value>>
を取得 - 2を購読してviewに反映する
class UserViewModel(private val: userRepository: UserRepository) : ViewModel() {
fun olderThan(age: Int): LiveData<PagedList<User>> {
val dataSourceFactory = object : DataSource.Factory<Long, User> {
override fun create(): DataSource<Long, User> = UserDataSourceFactory(age, userRepository)
}
return LivePagedListBuilder(
dataSourceFactory,
PagedList.Config.Builder()...build()
).build()
}
}
これで既存のRepositoryクラスに変更を加えることなくPaging Libraryを導入することができるかと思います。