Итак, я играю с новой библиотекой подкачки Android , входящей в состав инструментов JetPack.
Я делаю очень простое демонстрационное приложение, в котором я показываю список случайных пользовательских профилей.что я получаю от RandomUser API.
Дело в том, что у меня все настроено, и это на самом деле вроде работает.
В моем фрагменте списка я слушаю изменения БД:
...
mainViewModel.userProfiles.observe(this, Observer { flowableList ->
usersAdapter.submitList(flowableList) })
...
(я пробовал с обоими, используя Flowables
и Observables
с RxPagedListBuilder
и сейчасЯ использую LiveData
с LivePagedListBuilder
. Я хотел бы использовать RxPagedListBuilder
, если это возможно)
В моей ViewModel я устанавливаю LivePagedListBuilder
...
private val config = PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setPrefetchDistance(UserProfileDataSource.PAGE_SIZE / 2) //Is very important that the page size is the same everywhere!
.setPageSize(UserProfileDataSource.PAGE_SIZE)
.build()
val userProfiles: LiveData<PagedList<UserProfile>> = LivePagedListBuilder(
UserProfileDataSourceFactory(userProfileDao), config)
.setBoundaryCallback(UserProfileBoundaryCallback(randomUserRepository, userProfileDao))
.build()
...
Я установил DataSource для извлечения данных из моей БД (если есть):
class UserProfileDataSource(val userDao: UserDao): PageKeyedDataSource<Int, UserProfile>() {
companion object {
const val PAGE_SIZE = 10
}
override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, UserProfile>) {
callback.onResult(userDao.getUserProfileWithLimitAndOffset(PAGE_SIZE, 0), 0, PAGE_SIZE)
}
override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, UserProfile>) {
callback.onResult(userDao.getUserProfileWithLimitAndOffset(PAGE_SIZE, params.key), params.key + PAGE_SIZE)
}
override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, UserProfile>) {
//This one is not used
}
}
И я установил BoundaryCallback для извлечения данных из сети, если база данных пуста:
class UserProfileBoundaryCallback(val userRepository: RandomUserRepository,
val userDao: UserDao) : PagedList.BoundaryCallback<UserProfile>() {
/**
* Database returned 0 items. We should query the backend for more items.
*/
override fun onZeroItemsLoaded() {
userRepository.getUserProfiles(0, UserProfileDataSource.PAGE_SIZE)
.subscribeOn(Schedulers.io()) //We shouldn't write in the db over the UI thread!
.subscribe(object: DataSourceSubscriber<List<UserProfile>>() {
override fun onResultNext(userProfiles: List<UserProfile>) {
userDao.storeUserProfiles(userProfiles)
}
})
}
/**
* User reached to the end of the list.
*/
override fun onItemAtEndLoaded(itemAtEnd: UserProfile) {
userRepository.getUserProfiles(itemAtEnd.indexPageNumber + 1, UserProfileDataSource.PAGE_SIZE)
.subscribeOn(Schedulers.io()) //We shouldn't write in the db over the UI thread!
.subscribe(object: DataSourceSubscriber<List<UserProfile>>() {
override fun onResultNext(userProfiles: List<UserProfile>) {
userDao.storeUserProfiles(userProfiles)
}
})
}
}
Дело в том, что Flowable
, Observable
или LiveData
в пользовательском интерфейсе запускаются только в том случае, если данные поступают из базы данных, когда UserProfileDataSource
возвращает некоторый результат из базы данных,Если UserProfileDataSource
не возвращает никакого результата, вызывается BoundaryCallback, запрос к API успешно выполнен, данные сохраняются в базе данных, но Flowable
никогда не срабатывает.Если я закрою приложение и снова открою его, он получит данные, которые мы только что получили из базы данных, а затем правильно отобразит их.
Я испробовал все возможные решения, которые видел во всехстатьи, учебные пособия и проекты github, которые я искал.
Как я уже говорил, я пытался изменить RxPagedListBuilder
на LivePagedListBuilder
.
При использовании RxPagedListBuilder
я пробовал с обоими, Flowables
и Observables
.
Я пытался установить различные конфигурации для PagedList.Config.Builder
с использованием разных планировщиков.
У меня действительно нет вариантов, я весь день боролсяс этим, любой совет будет оценен.
Если вам нужна дополнительная информация о коде, просто оставьте мне комментарий, и я обновлю сообщение.
Обновление:
Я отправил полный исходный код в мое Github репо