やりたいこと
PagedListAdapter をセットした RecyclerView を再度読み込みし直したい。
シチュエーション
例:Material Design > Backdrop スタイルの検索結果一覧画面にて
- 「検索ワード」が変更されたり「絞り込みの条件」が追加された場合に検索結果一覧をリロードしたい
- 検索結果一覧が Swipe-to-Refresh された場合
など。
試み
PagedListAdapter を再生成して RecyclerView にセットし直すというようなチャチな発想では全然ダメでした
参考
公式の googlesamples/android-architecture-components/PagingWithNetworkSample/ を解読します。
天才・Googler 様が考える実装はクセがスゴかったです。
仕組み
「検索ワード」や「絞り込みの条件」が変化した場合
ViewModel が保持する検索条件に関する MutableLiveData の値を更新して RecyclerView をリフレッシュしています。
Swipe-to-Refresh した場合
ネットワーク上からデータを取得していれば DataSource.invalidate() を呼び、Room からデータを取得していればネットワーク上からデータを取り直しトランザクション終了後自動的に反映されます。
実践
2018 年 7 月 8 日時点の公式のサンプルは「検索ワード」のみが RecyclerView をリフレッシュするトリガーになっていますが、「検索ワード」と「絞り込みの条件」が変化した場合に検索結果一覧をリロードする方法について考えてみました。
サンプル
- 複数ある検索条件を1つにまとめたデータクラス
SearchParameter
を定義 -
ViewModel で
SearchParameter
の MutableLiveData を保持 - 検索条件が変化して検索結果一覧を更新したい場合は MutableLiveData.setValue() を実施します
/**
* 複数の検索条件をまとめたデータクラス
*/
data class SearchParameter(
var keyword: String?, // キーワード
var minPrice: Int?, // 価格の下限
var maxPrice: Int?, // 価格の上限
var size: Int? // 大きさ
)
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)
}
}