idanatz / OneAdapter

A Viewholderless Adapter for RecyclerView, who supports builtin diffing, states (paging, empty...), events (clicking, swiping...), and more.
MIT License
470 stars 45 forks source link

Question:Paging with Room Datasource #36

Open thexaib opened 3 years ago

thexaib commented 3 years ago

Hi, this is more a question than an issue, related to Room Datasource+LiveData PagedList. I want to use selectable item feature of the OneAdapter, so i am trying to change currently working RecyclerView with PagedListAdapter. But for OneAdapter, i need to ask PagedList from Room datasource to load next items , which i could not find how can it be done. As i understand PagedListAdapter requests next loading of items automatically by calculating Item size and recyclerview viewport size. and calls pagedlist.loadAround(Int) . I am not sure about the Int value passed here, its probably the internally maintained enumerated index of current list. I could not find how can i request next page to load in viewmodel. Did anyone can direct me how to use Room Paging Datasource with OneAdapter.?

OneAdapter Impl

object OneAdapters {

    fun create(recyclerView: RecyclerView, onClick:(ModelEntity)->Unit,onCurrentBind:(Int)->Unit,loadMoreCall:(Int)->Unit) =OneAdapter(recyclerView){
        itemModules+=ExperimentModelItem(onClick,onCurrentBind)
        pagingModule=PagingModuleImpl(loadMoreCall)
    }

    internal class ExperimentModelItem(onClick: (ModelEntity) -> Unit,onCurrentBind: (Int) -> Unit) : ItemModule<ModelEntity>() {

        init {
            config {
                layoutResource = R.layout.item_tile_list
            }
            onBind { model, viewBinder, metadata ->

                viewBinder.bindings(ItemTileListBinding::bind).run {
                    onCurrentBind(metadata.position)
                    title.text = model.modelname
                    model.modified_at?.let { d ->
                        subtitle.text = "modified ${DateFormatHelper.readable(d)}"
                    }
                }
            }
            onUnbind { model, viewBinder, _ ->
            }

            eventHooks += ClickEventHook<ModelEntity>().apply {
                onClick { model, viewBinder, _ ->
                    onClick(model)
                }
            }
        }

    }
    internal class PagingModuleImpl(loadMoreCall:(Int)->Unit) : PagingModule() {
        init {
            config {
                layoutResource = R.layout.item_loading_progress// can be some spinner animation
                visibleThreshold = 0 // invoke onLoadMore 3 items before the end
            }
            onLoadMore { currentPage ->
                // place your load more logic here, like asking the ViewModel to load the next page of data.
                loadMoreCall(currentPage)
            }
        }
    }
}

Activity

private var mListMaxPosition: Int = 0
    private val mRecyclerAdapter: OneAdapter by lazy {
        OneAdapters.create(binding.explistActivityRecylerview, onClick = {
            // navigate
        },
            onCurrentBind = {
                if (it > mListMaxPosition)
                    mListMaxPosition = it 
            },
            loadMoreCall = {
                viewmodel.add(VMEvent.LoadMore(mListMaxPosition))
            })
    }

viewmodel

init{
 val factory =repo.getAllModelsFactory()
        val config = PagedList.Config.Builder()
            .setEnablePlaceholders(false) // when true, the oneadapter's internal adapter crash on validating list having null models   
            .setInitialLoadSizeHint(15)
            .setPageSize(5).build()

        val pagedListBuilder: LivePagedListBuilder<Int, ModelEntity>  = LivePagedListBuilder<Int,ModelEntity>(
            factory,
            config
            )
models=pagedListBuilder.build() // observed LiveData in activity
}
fun    onLoadMore(currentPage:Int) // called from activity, 
{
   models.value?.let {
     // it.loadAround(currentPage) // max intPosition comming from activity
    //it.loadAround(it.lastKey as Int)

   }

}
idanatz commented 3 years ago

Hi, In order to work with Paging3, you will need your adapter to inherited from PagingDataAdapter. (source)

OneAdapter is based on RecyclerView.Adapter and not PagingDataAdapter because I didn't want to rely on a brand new library (when it just came out) as a base for my library.

I wanted to add some kind of support back in the day for Paging2 but the paging library keeps changing and v2 is no longer that attractive. When Paging3 will be out of alpha and will prove its maturity I will try to add a way OneAdapter can integrate with it.

thexaib commented 3 years ago

i also played around with paging 3, but i did not see much control on manually fetching next page and paging 2 looked like it could be done. but i failed :P. looking forward to paging adapter support.