PagedListAdapter перезагрузить данные без заполнителей - PullRequest
3 голосов
/ 31 мая 2019

Я использую PagedListAdapter, и мне нужно перезагрузить данные, когда экран возобновляется.
В этом случае я не хочу очищать адаптер и показывать его пустым или заполнители во время загрузки данных.
Я хочу показать предыдущие данные и просто обновить их с помощью diff после получения новых данных.
Но теперь, когда я делаю dataSource.invalidate(), он немедленно отправляет пустой список, который вызывает очистку адаптера и отображение заполнителей.

Теперь мой код выглядит следующим образом:

class PortfolioListDataSource(
        private val viewModel: PortfolioViewModel,
        private val tabType: PortfolioTabType
) : PageKeyedDataSource<Int, Investment>() {

    override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Investment>) {
        val offset = 0
        viewModel.loadInvestments(tabType, offset, Consumer {
            val nextKey = if (it.data.size < params.requestedLoadSize) null else it.data.size
            callback.onResult(it.data, offset, it.total, null, nextKey)
        })
    }

    override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Investment>) {
        val offset = params.key
        viewModel.loadInvestments(tabType, offset, Consumer {
            val nextKey = offset + it.data.size
            callback.onResult(it.data, nextKey)
        })
    }

    override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, Investment>) {

    }

    class Factory(
            val viewModel: PortfolioViewModel,
            private val tabType: PortfolioTabType
    ) : DataSource.Factory<Int, Investment>() {

        val sourceLiveData = MutableLiveData<PortfolioListDataSource>()

        override fun create() = PortfolioListDataSource(viewModel, tabType)
                .also { sourceLiveData.postValue(it) }
    }
}

Здесь я инициализирую

val pagedListConfig = PagedList.Config.Builder()
            .setInitialLoadSizeHint(20)
            .setPageSize(20)
            .build()

ordersLiveData = LivePagedListBuilder(factory, pagedListConfig).build()

Здесь я заполняю адаптер

viewModel.ordersLiveData.observe(this, Observer {
    adapter.submitList(it)
})

И обновляем его с помощью

// TODO Here I want to fetch new data, but not invalidate current dataset while it is loading
factory.sourceLiveData.value?.invalidate()

Как я могу оставить предыдущие данные и обновить их, когда новые данные будут готовы?

Обновление:
Я хочу что-то вроде:

if (!refreshing) {
   submitList(it)
}

Я имею в виду не публиковать пустой набор данных в адаптер, когда вызывается dataSource.invalidate().

Я понимаю, что упомянутое выше пример не сработает, потому что после отправки источник данных передает обновления тому же экземпляру списка, и он полностью инкапсулируется.
Кроме того, я не влияю насам набор данных.

Я пытался использовать PagedList.Callback, это позволяет узнать, когда список обновляется.Но опять же, нет никаких шансов как-то повлиять на поведение обновления.

С обычным адаптером я бы просто не устанавливал и не обновлял его элементы до тех пор, пока не будут получены новые данные.Я хочу добиться чего-то подобного здесь.

1 Ответ

1 голос
/ 09 июня 2019

Да, invalidate () очистит текущий набор данных.Итак, вы попадете в состояние загрузки / заполнителя.Также невозможно обновить определенную страницу.Скажем, вы находитесь на 5-й странице и хотите обновить данные на этой конкретной странице.Это также невозможно без вызова invalidate (), который очистит набор данных и переместится в Recyclerview на первую страницу (верхнюю часть списка).

Единственный способ избавиться от всех этих проблем - ввести слой постоянства с помощью Room.https://github.com/googlesamples/android-architecture-components/tree/master/PagingWithNetworkSample#paging-with-database-and-network

Согласно документам здесь: https://developer.android.com/reference/androidx/paging/DataSource#updating-paged-data

Если у вас есть более детализированные сигналы обновления, такие как сетевой API, сигнализирующий об обновлении одного элемента в списке,рекомендуется загружать данные из сети в память.Затем представьте эти данные в PagedList через DataSource, который оборачивает снимок в памяти.Каждый раз, когда изменяется копия в памяти, аннулируется предыдущий источник данных, и может создаваться новый, содержащий новое состояние моментального снимка.

https://developer.android.com/topic/libraries/architecture/paging/data#consider-content-updates

Когда вы создаете наблюдаемые объекты PagedList, подумайте, как работают обновления контента.Если вы загружаете данные непосредственно из баз данных обновлений, они автоматически отправляются в пользовательский интерфейс вашего приложения.

В вашем случае вы всегда можете загрузить данные из БД при возобновлении экрана, покаданные из вашего API извлекаются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...