Which is the best way to update a single element when using the new paging library?
Let's say we have the Paging with network google sample using the PageKeyedSubredditDataSource
. Imagine we want to make a change of a single element of RedditPost
. So, we want to check if it is in the list and if so, update it. The update should not be as easy as calling invalidate() which will make a call to the first page (maybe the RedditPost is in the 5th page. We don't want to update all elements, just one).
The Paging library works with all of these components and coordinates the interactions between them, so that it can load "pages" of content from a data source and display that content in the UI. PagingData - a container for paginated data.
PagingConfig defines how to get data from the PagingSource like page size, prefetch distance, etc. Check official docs for the parameters you can set for PagingSource. An optional initialKey to start loading with a default key. When the Pager object is created, it calls the load () function of the pagingSourceFactory it has.
The Paging API provides support for many of the functionalities that you would otherwise need to implement manually when you need to load data in pages: Keeps track of the keys to be used for retrieving the next and previous page. Automatically requests the correct page when the user has scrolled to the end of the list.
Currently, Paging 3 is available as an alpha release. If you want to use a stable version you can use Paging 2. This post will be about Paging 3. Paging 3 comes with some considerable differences from the earlier versions. Some of them are:
Please note that all this works over the Paging with network google sample. Although that, the idea is there.
@Sarquella helped me with this solution. Add this classes to your project. Basically we are extending ViewHolder
to be LifeCycle Owner
, as it is already done by default with Activities
and Fragments
.
The LifecycleViewHolder
:
abstract class LifecycleViewHolder(itemView: View) :
RecyclerView.ViewHolder(itemView),
LifecycleOwner {
private val lifecycleRegistry = LifecycleRegistry(this)
fun onAttached() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)
}
fun onDetached() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
}
override fun getLifecycle(): Lifecycle = lifecycleRegistry
}
LifecycleOwner
is a single method interface that denotes that the class has a Lifecycle
. You can find more information here.
The LifecyclePagedListAdapter
:
abstract class LifecyclePagedListAdapter<T, VH : LifecycleViewHolder>(diffCallback: DiffUtil.ItemCallback<T>) :
PagedListAdapter<T, VH>(diffCallback) {
override fun onViewAttachedToWindow(holder: VH) {
super.onViewAttachedToWindow(holder)
holder.onAttached()
}
override fun onViewDetachedFromWindow(holder: VH) {
super.onViewDetachedFromWindow(holder)
holder.onDetached()
}
}
The LifecycleAdapter
(in the case you need it):
abstract class LifecycleAdapter<VH : LifecycleViewHolder> :
RecyclerView.Adapter<VH>() {
override fun onViewAttachedToWindow(holder: VH) {
super.onViewAttachedToWindow(holder)
holder.onAttached()
}
override fun onViewDetachedFromWindow(holder: VH) {
super.onViewDetachedFromWindow(holder)
holder.onDetached()
}
}
Then, extends MyAdapter
to LifecyclePagedListAdapter<MyEntity, LifecycleViewHolder>(MY_COMPARATOR)
and MyViewHolder
to LifecycleViewHolder(view)
. You'll have to complete your classes based on what we have changed, accordingly. Now we can observe to a liveData
object on MyViewHolder
class. So we can add this to MyViewHolder
class (assuming you're using Dependency Injection). Basically, we'll do the same we do for Fragments
or Activities
:
private lateinit var myViewModel: MyViewModel
init {
(itemView.context as? AppCompatActivity)?.let{
myViewModel = ViewModelProviders.of(it).get(MyViewModel::class.java)
}
}
Then, inside the bind()
method:
fun bind(myCell: MyEntity?) {
myViewModel.myLiveData.observe(this, Observer {
// Buala!! Check if it is the cell you want to change and update it.
if (it != null && myCell != null && it.id == myCell.id) {
updateCell(it)
}
})
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With