У нас обычно есть моделька для логики, что-то типа
data class Human(val age: Int, val sex: Boolean, val height: Float): AutoParcelable
, где-то есть State, в котором хранится список таких моделек:
data class State(val humans: List<Human>): AutoParcelable
Есть стрим состояний
Observable<State>
. Для того, чтобы отобразить стейт на экране, есть ViewState:
data class HumanViewState(val formattedAge: String, val sex: Boolean, val formattedHeight: String)
data class ViewState(humans: List<HumanViewState>, diff: DiffUtil.DiffResult?)
есть маппер, который в бекграунде маппит стейты во вьюстейты, что-то типа:
class ViewStateMapper @Inject constructor(stateProvider: StateProvider<State>>) {
fun viewStates(): Observable<ViewState> = stateProvider.states // эмиттит на бекграунд треде
.distinctUntilChanged()
.map {
// State -> ViewState
}.scan {
// вычислить дифф между текущим и предыдущим вьюстейтами
}
}
и, в конце концов, есть вьюха, которая подписывается на маппер и рендерит стейты:
fragment/controller/etc
fun onViewCreated(....) {
....
mapper.viewStates
.observeOn(mainThreadScheduler)
.subscribe(::render)
.disposeWithView()
}
private fun render(viewState: ViewState) {
recyclerAdapter.items = viewState.humans
viewState.diff?.dispatchUpdatesTo(recyclerAdapter) ?: recyclerAdapter.notifyDatasetChanged()
}