I already did all the competent of the paging library tried to send all data to the UI following this artricle but no luck on getting the data here is my code
When I debugged I found the following:
when it's loading the network state and pagedUserList get notified for the first time and when the request DONE only the network state get notified and the list doesn't get notified with the list itself and I don't know why? any clue?
MainActivity
private fun initAdapter() {
newsListAdapter = NewsListAdapter { mainViewModel.retry() }
binder.rvUsers.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
binder.rvUsers.adapter = newsListAdapter
mainViewModel.getPagedList().observe(this, Observer {
newsListAdapter.submitList(it)
})
}
private fun initState() {
binder.txtError.setOnClickListener { mainViewModel.retry() }
mainViewModel.getState().observe(this, Observer { state ->
binder.progressBar.visibility =
if (mainViewModel.listIsEmpty() && state == State.LOADING) View.VISIBLE else View.GONE
binder.txtError.visibility =
if (mainViewModel.listIsEmpty() && state == State.ERROR) View.VISIBLE else View.GONE
if (!mainViewModel.listIsEmpty()) {
newsListAdapter.setState(state ?: State.DONE)
}
})
}
ViewModel
private var pagedUserList: LiveData<PagedList<User>>
private val compositeDisposable = CompositeDisposable()
private val pageSize = 10
private val usersDataSourceFactory: UsersDataSourceFactory
init {
usersDataSourceFactory = UsersDataSourceFactory(usersService, compositeDisposable)
val config = PagedList.Config.Builder()
.setPageSize(pageSize)
.setInitialLoadSizeHint(pageSize * 3)
.setEnablePlaceholders(false)
.build()
pagedUserList = LivePagedListBuilder<Int, User>(usersDataSourceFactory, config)
.build();
}
fun getState(): LiveData<State> = Transformations.switchMap<UsersDataSource,
State>(usersDataSourceFactory.getUserLiveData(), UsersDataSource::state)
fun retry() {
usersDataSourceFactory.getUserLiveData().value?.retry()
}
fun listIsEmpty(): Boolean {
return pagedUserList.value?.isEmpty() ?: true
}
fun getPagedList(): LiveData<PagedList<User>> {
return pagedUserList
}
DataSourceFactory
class UsersDataSourceFactory(
private val usersService: UsersService,
private val compositeDisposable: CompositeDisposable
) : DataSource.Factory<Int, User>() {
private val usersDataSourceLiveData = MutableLiveData<UsersDataSource>()
override fun create(): DataSource<Int, User> {
val usersDataSource = UsersDataSource(usersService, compositeDisposable)
usersDataSourceLiveData.postValue(usersDataSource)
return usersDataSource
}
fun getUserLiveData() = usersDataSourceLiveData
}
DataSource
class UsersDataSource(
private val usersService: UsersService,
private val compositeDisposable: CompositeDisposable
) : PageKeyedDataSource<Int, User>() {
var state: MutableLiveData<State> = MutableLiveData()
private var retryCompletable: Completable? = null
override fun loadInitial(
params: LoadInitialParams<Int>,
callback: LoadInitialCallback<Int, User>
) {
updateState(State.LOADING)
compositeDisposable.add(
usersService.getUsers(0, 20)
.subscribe({ response: List<User> ->
updateState(State.DONE)
val nextPageKey = response[response.size - 1].id
callback.onResult(
response, null, nextPageKey
)
}, { t: Throwable? ->
updateState(State.ERROR)
setRetry(Action { loadInitial(params, callback) })
})
)
}
override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, User>) {
updateState(State.LOADING)
compositeDisposable.add(
usersService.getUsers(params.key + 1, 20)
.subscribe({ response: List<User> ->
updateState(State.DONE)
if (!response.isEmpty()) {
val nextPageKey = response[response.size - 1].id
callback.onResult(response, nextPageKey)
}else {
updateState(State.ERROR)
setRetry(Action { loadAfter(params, callback) })
}
}, { t: Throwable? ->
updateState(State.ERROR)
setRetry(Action { loadAfter(params, callback) })
})
)
}
override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, User>) {
}
private fun updateState(state: State) {
this.state.postValue(state)
}
fun retry() {
if (retryCompletable != null) {
compositeDisposable.add(
retryCompletable!!
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe()
)
}
}
private fun setRetry(action: Action?) {
retryCompletable = if (action == null) null else Completable.fromAction(action)
}
}
enum class State {
DONE, LOADING, ERROR
}