Edited at

Android Jetpack の Paging を用いたリストを再読み込みするまでの長かった道のり

More than 1 year has passed since last update.


やりたいこと

PagedListAdapter をセットした RecyclerView を再度読み込みし直したい。


シチュエーション

例:Material Design > Backdrop スタイルの検索結果一覧画面にて


  • 「検索ワード」が変更されたり「絞り込みの条件」が追加された場合に検索結果一覧をリロードしたい

  • 検索結果一覧が Swipe-to-Refresh された場合

など。

backdrop-shrine-ahero.png


試み

PagedListAdapter を再生成して RecyclerView にセットし直すというようなチャチな発想では全然ダメでした :no_good:


参考

公式の googlesamples/android-architecture-components/PagingWithNetworkSample/ を解読します。

Screenshot_1530550075.png

天才・Googler 様が考える実装はクセがスゴかったです。


仕組み


「検索ワード」や「絞り込みの条件」が変化した場合

ViewModel が保持する検索条件に関する MutableLiveData の値を更新して RecyclerView をリフレッシュしています。


Swipe-to-Refresh した場合

ネットワーク上からデータを取得していれば DataSource.invalidate() を呼び、Room からデータを取得していればネットワーク上からデータを取り直しトランザクション終了後自動的に反映されます。


実践

2018 年 7 月 8 日時点の公式のサンプルは「検索ワード」のみが RecyclerView をリフレッシュするトリガーになっていますが、「検索ワード」と「絞り込みの条件」が変化した場合に検索結果一覧をリロードする方法について考えてみました。


サンプル


  1. 複数ある検索条件を1つにまとめたデータクラス SearchParameter を定義


  2. ViewModelSearchParameterMutableLiveData を保持

  3. 検索条件が変化して検索結果一覧を更新したい場合は MutableLiveData.setValue() を実施します


SearchParameter.kt

/**

* 複数の検索条件をまとめたデータクラス
*/
data class SearchParameter(
var keyword: String?, // キーワード
var minPrice: Int?, // 価格の下限
var maxPrice: Int?, // 価格の上限
var size: Int? // 大きさ
)


SearchViewModel.kt

class SearchViewModel(private val repository: SearchRepository) : ViewModel() {

private val searchParameterMutableLiveData = MutableLiveData<SearchParameter>()

private val repoResult = map(searchParameterMutableLiveData) { searchParameter ->
repository.search(searchParameter = searchParameter, pageSize = 20)
}

val searchResults = switchMap(repoResult) { it.pagedList }!!

/**
* 条件を指定して検索を実施
*/
fun search(keyword: String?, minPrice: Int?, maxPrice: Int?, size: Int?) {
searchParameterMutableLiveData.value = SearchParameter(
keyword = keyword,
minPrice = minPrice,
maxPrice = maxPrice,
size = size)
}
}