I am using a android paging library to display a list of data in a fragment. It works, but when i rotate the screen, the list is loaded again instead of get already loaded data. I did it for this article. What is the problem?
This is my RxPagingSource
public Single<LoadResult<Integer, Book>> loadSingle(@NotNull LoadParams<Integer> loadParams) {
Integer nextPageNumber = loadParams.getKey();
if (nextPageNumber == null) {
nextPageNumber = 1;
}
return dataApi.getBooksCatalog(nextPageNumber, new ArrayMap<>(), preferencesHelper.auth())
.subscribeOn(Schedulers.io())
.map(this::toLoadResult)
.onErrorReturn(LoadResult.Error::new);
}
private LoadResult<Integer, Book> toLoadResult(ResponseData<DataList<Book>> response) {
int currentPage = response.getData().getCurrentPage();
return new LoadResult.Page<>(
response.getData().getData(),
currentPage > 1 ? currentPage - 1 : null,
response.getData().getData().isEmpty() ? null : currentPage + 1);
}
public Integer getRefreshKey(@NotNull PagingState<Integer, Book> pagingState) {
Integer anchorPosition = pagingState.getAnchorPosition();
if (anchorPosition == null) {
return null;
}
LoadResult.Page<Integer, Book> anchorPage = pagingState.closestPageToPosition(anchorPosition);
if (anchorPage == null) {
return null;
}
Integer prevKey = anchorPage.getPrevKey();
if (prevKey != null) {
return prevKey + 1;
}
Integer nextKey = anchorPage.getNextKey();
if (nextKey != null) {
return nextKey - 1;
}
return null;
}
I did not understand in which case the getRefreshKey() method should be called.
PagingDataAdapter<T, V> and DiffUtil.ItemCallback are standard...
In My ViewModel
@HiltViewModel
public class BooksViewModel extends BaseDisposablesViewModel {
PagingConfig pagingConfig = new PagingConfig(50, 25, true, 100, 200);
private final DataApiInterface dataApi;
private final SharedPreferencesHelper preferencesHelper;
Flowable<PagingData<Book>> flowable;
@Inject
BooksViewModel(DataApiInterface dataApi, SharedPreferencesHelper preferencesHelper) {
this.dataApi = dataApi;
this.preferencesHelper = preferencesHelper;
init();
}
private void init() {
CoroutineScope viewModelScope = ViewModelKt.getViewModelScope(this);
Pager<Integer, Book> pager = new Pager<>(
pagingConfig,
() -> new BooksPagingSource(dataApi, preferencesHelper)
);
flowable = PagingRx.getFlowable(pager);
PagingRx.cachedIn(flowable, viewModelScope);
}
}
And my Fragment...
@AndroidEntryPoint
public class BooksFragment extends BaseFragment {
private FragmentBooksBinding binding;
private final CompositeDisposable disposable = new CompositeDisposable();
private BooksPagingAdapter pagingAdapter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BooksViewModel viewModel = new ViewModelProvider(requireActivity()).get(BooksViewModel.class);
pagingAdapter = new BooksPagingAdapter(new BooksPagingAdapter.BookComparator());
disposable.add(viewModel.flowable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(bookPagingData -> pagingAdapter.submitData(getLifecycle(), bookPagingData)));
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentBooksBinding.inflate(inflater, container, false);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.list.setAdapter(pagingAdapter);
}
@Override
public void onDestroy() {
super.onDestroy();
disposable.clear();
}
}