Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to update a single element using Paging Library

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).

like image 419
Damia Fuentes Avatar asked May 31 '18 00:05

Damia Fuentes


People also ask

How does the paging library work?

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.

How to get data from the pagingsource?

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.

What can I do with the paging API?

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.

Is paging 3 a stable version of paging?

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:


1 Answers

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)
        }
    })
}
like image 71
Damia Fuentes Avatar answered Oct 21 '22 10:10

Damia Fuentes