3

Android Paging3 alpha03, How to remove or update item?

Help,please

mumu
  • 39
  • 1
  • 2

1 Answers1

3

The only way to update the backing dataset currently is to call PagingSource.invalidate to trigger another REFRESH, which then reloads from current position via PagingSource.getRefreshKey(state).

e.g.,

val backingDataSet = mutableListOf(1, 2, 3)
class MyPagingSource : PagingSource<Int, Int> {
    override suspend fun load(...) = Page(
        data = backingDataset,
        nextKey = null,
        prevKey = null,
        itemsBefore = 0,
        itemsAfter = 0
    )

    override fun getRefreshKey(state: PagingState<Int, Int>) = state.anchorPosition
}

...

var currentPagingSource: MyPagingSource? = null
val pager = Pager(...) {
    MyPagingSource().also{
        currentPagingSource = it
    }
}

...

// To remove an item
backingDataSet.removeAt(0)
currentPagingSource.invalidate()
dlam
  • 3,547
  • 17
  • 20
  • Thanks, Can I specify to refresh the second page data? – mumu Aug 08 '20 at 07:10
  • Currently you must invalidate the entire source. – dlam Aug 08 '20 at 15:41
  • @dlam What about using `peek()` to modify an item and then calling `notifyItemChanged`? Is this a bad approach? – Florian Walther Jan 10 '21 at 11:02
  • @FlorianWalther Always invalidate after updates to the backing dataset. Trying to sync local state with paginated backing data is really hard to do correctly and you won't get help on that path. For example, how will you resolve races between notifyItem and a prepend or a drop? Another hard case is restoring from cached PagingData, you will need to figure out what is presented and re-insert the correct item. SavedState is even more complicated. So I would definitely not recommend to try to be clever by using notify directly. – dlam Jan 11 '21 at 18:35
  • @dlam Thank you for the input. If I have 500 paginated items on the list a call to `invalidate` will reload them all from the source? Is that correct? – Florian Walther Jan 11 '21 at 18:42
  • @dlam I don't understand what you're referring to about "cached PagingData" and SavedState. Paging 3 reloads the whole page after process death, right? So it should get the updated data. Screen rotation works as well because I've updated the list that backs the adapter. – Florian Walther Jan 11 '21 at 18:50
  • It depends on your initialLoadSize and/or pageSize. Invalidate will reload, but you should implement getRefreshKey to resume from last bound item and ensure you load around the entire viewport (+/- 1 page at minimum) but its very crucial to to have a single source of truth or things will get quickly out of hand. So invalidate will call getRefreshKey to figure out how to resume loading and only load data centered around user's position, not all 500 items. – dlam Jan 12 '21 at 01:43
  • Answering your questions - SavedState case without RemoteMediator and placeholders enabled will work automatically. On process death, yes things are reloaded starting from initialKey. There is a .cachedIn operator which condenses the internal event stream in a PagingData and multicasts it within a scope, this cached event will be out-of-date if you update items manually without going through paging and its important you make use of this operator as well – dlam Jan 12 '21 at 01:48