Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating PagedListAdapter after initial load to show latest network data

I'm utilizing the new Paging library to load paginated data from a rest API, but I'm having trouble understanding how to continue loading fresh data after it's cached in Room. Currently, I have a PagedListAdapter that's updated by using a boundary callback to load items from API, which are then stored in the local DB (Room), which are emitted to the UI via a flowable.

onZeroItemsLoaded and onItemAtEndLoaded calls from the BoundaryCallback are all functioning as expected, but only for the initial load. Once the data is retrieved once and stored in cache (Room), I'll never get fresh data from the network service--there's already data in the cache and the boundary callbacks are not triggered.

How do you mark items stale using the paging library so that every time the app opens my data is fresh?

ItemCallback.kt:

class ItemBoundaryCallback : PagedList.BoundaryCallback<Item>() {
        override fun onZeroItemsLoaded() {
            itemsFromNetwork(0)
        }

        override fun onItemAtEndLoaded(itemAtEnd: Item) {
            itemsFromNetwork(itemAtEnd.rank)
        }
    }

ItemRepository.kt:

fun items(): Flowable<PagedList<Item>> {
    return RxPagedListBuilder(database.itemDao().items(), pageSize)
            .setBoundaryCallback(boundaryCallback)
            .buildFlowable(BackpressureStrategy.LATEST)
}

ItemDao.kt

@Query("SELECT * FROM item ORDER BY rank ASC")
fun items(): DataSource.Factory<Int, Item>

ItemAdapter.kt

class ItemAdapter() : PagedListAdapter<Item, ItemViewHolder>(diffCallback) {
    companion object {
        private val diffCallback = object : DiffUtil.ItemCallback<Item>() {
            override fun areItemsTheSame(old: Item, new: Item): Boolean = old.id == new.id
            override fun areContentsTheSame(old: Item, new: Item): Boolean = old == new
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
        return ItemViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.r_item, parent, false))
    }

    override fun onBindViewHolder(viewHolder: ItemViewHolder, position: Int) {
        viewHolder.bind(getItem(position), clickListener)
    }
}

ItemFragment.kt

override fun onStart() {
    super.onStart()

    itemRepository.items()
            .subscribe(itemAdapter::submitList)
            .addTo(disposables)
like image 532
0xMatthewGroves Avatar asked Jun 26 '18 03:06

0xMatthewGroves


People also ask

How do I update a single item in Pagedlistadapter?

A click on the like button should refresh the item.

What is paging data?

The Paging library helps you load and display pages of data from a larger dataset from local storage or over network. This approach allows your app to use both network bandwidth and system resources more efficiently.


1 Answers

The whole point of using this technique ( database and rest) is caching data and preventing to load them again. But if your data is not static and it may be changed or invalidated. you can have two approaches:

1 - Remove every record in the database after closing the app (or when starting the app. destroy callbacks are not viable), in this case, you will get fresh data after next start.

2 - Make a field in your database as "Expiration" date or something similar. keep checking the field on onItemAtFrontLoaded in boundaryCallback if they're expired you can invalidate and fetch it again from web service.

like image 74
Shynline Avatar answered Oct 11 '22 19:10

Shynline