Created
June 1, 2018 13:23
-
-
Save dmytroIncloud/31e76f688617f2836d5ee1b52fbc672a to your computer and use it in GitHub Desktop.
AsyncListDiffer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.support.v7.recyclerview.extensions.AsyncListDiffer | |
import android.support.v7.util.DiffUtil | |
import android.support.v7.widget.RecyclerView | |
import com.example.dimi.reactiveclean.extensions.paginator.PaginatorModelData | |
import com.example.dimi.reactiveclean.models.RecyclerUpdate | |
import com.example.dimi.reactiveclean.models.content.ContentDisplayable | |
import com.example.dimi.reactiveclean.models.content.ContentState | |
import com.example.dimi.reactiveclean.utils.DiffUtilCallbackContent | |
import com.example.dimi.reactiveclean.utils.DiffUtilContent | |
import com.example.dimi.reactiveclean.utils.SchedulersProvider | |
import com.hannesdorfmann.adapterdelegates3.ListDelegationAdapter | |
import io.reactivex.Single | |
import io.reactivex.disposables.Disposable | |
import timber.log.Timber | |
class NewsMainContentAdapter( | |
private val loadNextPage: () -> Unit, | |
val openCurrentContent: (ContentDisplayable.Content) -> Unit, | |
private val schedulers: SchedulersProvider | |
) : ListDelegationAdapter<MutableList<ContentDisplayable>>() { | |
private var disposable: Disposable? = null | |
private val asyncListDiffer: AsyncListDiffer<ContentDisplayable> = | |
AsyncListDiffer(this, DiffUtilCallbackContent()) | |
init { | |
items = mutableListOf() | |
delegatesManager.addDelegate(NewsMainContentDisplayableAdapter(openCurrentContent)) | |
.addDelegate(ProgressAdapter()) | |
.addDelegate(ErrorAdapter(loadNextPage)) | |
.setFallbackDelegate(AllDataAdapter()) | |
} | |
override fun onBindViewHolder( | |
holder: RecyclerView.ViewHolder, | |
position: Int, | |
payloads: MutableList<Any?> | |
) { | |
super.onBindViewHolder(holder, position, payloads) | |
if (position == items.size - DELTA_POSITION_LOADING && isContent()) loadNextPage.invoke() | |
} | |
fun setNewData(model: PaginatorModelData<ContentDisplayable>) { | |
disposable?.dispose() | |
val newList: MutableList<ContentDisplayable> = mutableListOf() | |
newList.addAll(model.content) | |
when (model.state) { | |
ContentState.DATA -> { | |
} | |
ContentState.PROGRESS -> newList.add(ContentDisplayable.Progress()) | |
ContentState.ERROR -> newList.add(ContentDisplayable.Error()) | |
ContentState.ALL_DATA -> newList.add(ContentDisplayable.AllContent()) | |
} | |
when (model.recyclerUpdate) { | |
RecyclerUpdate.DIFF_UTIL -> disposable = notifyDiffUtil(newList) | |
RecyclerUpdate.NOTIFY -> notifyRanges(newList) | |
RecyclerUpdate.DIFF_UTIL_ITEM_CALLBACK -> notifyDiffUtilCallback(newList) | |
} | |
} | |
fun disposeSubscription() { | |
disposable?.dispose() | |
} | |
private fun isContent() = items.last() is ContentDisplayable.Content | |
private fun notifyDiffUtil(newList: List<ContentDisplayable>): Disposable { | |
return Single.fromCallable { DiffUtil.calculateDiff(DiffUtilContent(items, newList)) } | |
.compose(::composeSchedulers) | |
.subscribe( | |
{ | |
items.apply { clear() }.addAll(newList) | |
it.dispatchUpdatesTo(this@NewsMainContentAdapter) | |
}, | |
{ throw Exception(it.message) } | |
) | |
} | |
private fun notifyRanges(newList: List<ContentDisplayable>) { | |
items.apply { clear() }.addAll(newList) | |
notifyDataSetChanged() | |
} | |
private fun notifyDiffUtilCallback(newList: List<ContentDisplayable>) { | |
items.apply { | |
clear() | |
addAll(newList) | |
} | |
asyncListDiffer.submitList(newList) | |
} | |
private fun composeSchedulers(single: Single<DiffUtil.DiffResult>): Single<DiffUtil.DiffResult> = | |
single.subscribeOn(schedulers.computation()) | |
.observeOn(schedulers.ui()) | |
companion object { | |
const val DELTA_POSITION_LOADING = 5 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment