I'm using the Paging Architecture Components in my project to load a list from the network (no database usage yet). My DataSource
is a PositionalDataSource
subclass, and my PagedList.Config
looks like this:
PagedList.Config config = new PagedList.Config.Builder()
.setPageSize(10)
.setInitialLoadSizeHint(20)
.setPrefetchDistance(20)
.setEnablePlaceholders(true)
.build();
Placeholders are enabled, and I handle null ViewHolders in my PagedListAdapter
subclass to display placeholder items differently. The placeholders work fine when loading additional items at the end of the list, but I also want to display a placeholder item before the first few items are loaded (like a regular loading indicator).
Is there a way to do this with the Paging library? I tried to call LoadInitialCallback.onResult()
with a position of 1
instead of 0
, but this only creates a placeholder item before the first real item, and that placeholder item never disappears.
The Paging Library lets you load data directly from your backend using keys that the network provides. Your data can be uncountably large. Using the Paging Library, you can load data into pages until there isn't any data remaining. You can observe your data more easily.
PagedList can present data for an unbounded, infinite scrolling list, or a very large but countable list. Use PagedList. Config to control how many items a PagedList loads, and when. If you use LivePagedListBuilder to get a LiveData <PagedList>, it will initialize PagedLists on a background thread for you.
Display the paged data in your UICreate an instance of your PagingDataAdapter class. Pass the PagingDataAdapter instance to the RecyclerView list that you want to display your paged data. Observe the PagingData stream, and pass each generated value to your adapter's submitData() method.
Repository layer Each PagingSource object defines a source of data and how to retrieve data from that source. A PagingSource object can load data from any single source, including network sources and local databases.
I realize this question is rather old but I answer this, since this is where I ended up from googling the issue . In v3 there are LoadStateAdapter which you can add to Header and Footer for Prepend and Append load states. Initial load will be the refresh state which does not seem to be included but we can simply copy the functionality and extend it to include Refresh:
I simply copied withLoadStateHeaderAndFooter and added a third adapter that could be used for refresh
private fun PagingAdapter.withLoadStateAll(
header: LoadStateAdapter<*>,
footer: LoadStateAdapter<*>,
refresh: LoadStateAdapter<*>
): ConcatAdapter {
addLoadStateListener { loadStates ->
header.loadState = loadStates.prepend
footer.loadState = loadStates.append
refresh.loadState = loadStates.refresh
}
return ConcatAdapter(refresh,header, this, footer)
}
then you can simply register this to your Recycler as per the documentation and it'll show during initial load.
recycler.adapter = adapter.withLoadStateAll(LoadAdapter(),LoadAdapter(),LoadAdapter())
If you need to show more than one item during initial load simply copy LoadStateAdapter and change the number of items from 1 to n:
class InitialLoadAdapter(private val num : Int) : RecyclerView.Adapter<LoadViewHolder>() {
var loadState: LoadState = LoadState.NotLoading(endOfPaginationReached = false)
set(loadState) {
if (field != loadState) {
val oldItem = displayLoadStateAsItem(field)
val newItem = displayLoadStateAsItem(loadState)
if (oldItem && !newItem) {
notifyItemRangeRemoved(0,num)
} else if (newItem && !oldItem) {
notifyItemRangeInserted(0,num)
} else if (oldItem && newItem) {
notifyItemRangeChanged(0,num)
}
field = loadState
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LoadViewHolder {
return LoadViewHolder(parent)
}
override fun onBindViewHolder(holder: LoadViewHolder, position: Int) {}
override fun getItemViewType(position: Int): Int = getStateViewType(loadState)
override fun getItemCount(): Int = if (displayLoadStateAsItem(loadState)) num else 0
private fun getStateViewType(loadState: LoadState): Int = 0
private fun displayLoadStateAsItem(loadState: LoadState): Boolean {
return loadState is LoadState.Loading || loadState is LoadState.Error
}
}
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