I using the Paging library in my project.
In Activity, an observer observes the data that the Room library return, when the Room's data changes, the UI update.
And when I scroll to the end of the RecyclerView, the Paging library starts to load data into Room.
But the RecyclerView's list refreshes incorrectly and scroll to the previous position.
What's wrong with my code?
PagingItemRepository repository = new PagingItemRepository(FindDatabase.getInstance(PagingListActivity.this).pagingItemDao());
repository.getAllItems().observe(this, new Observer<PagedList<ItemEntity>>() {
@Override
public void onChanged(PagedList<ItemEntity> itemEntities) {
adapter.submitList(itemEntities);
}
});
Adapter
class PagingListAdapter extends PagedListAdapter<ItemEntity, ItemHolder> {
protected PagingListAdapter() {
super(DIFF_CALLBACK);
}
protected PagingListAdapter(@NonNull DiffUtil.ItemCallback<ItemEntity> diffCallback) {
super(diffCallback);
}
@NonNull
@Override
public ItemHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ItemHolder(LayoutInflater.from(PagingListActivity.this).inflate(R.layout.list_item, parent, false));
}
@Override
public void onBindViewHolder(@NonNull ItemHolder holder, int position) {
ItemEntity entity = getItem(position);
if (entity != null) {
String value = entity.getText();
holder.textView.setText(value);
}
}
}
class ItemHolder extends RecyclerView.ViewHolder {
TextView textView;
public ItemHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.text);
}
}
DiffUtil
private static DiffUtil.ItemCallback<ItemEntity> DIFF_CALLBACK =
new DiffUtil.ItemCallback<ItemEntity>() {
// Concert details may have changed if reloaded from the database,
// but ID is fixed.
@Override
public boolean areItemsTheSame(ItemEntity oldEntity, ItemEntity newEntity) {
return oldEntity.getId() == newEntity.getId();
}
@Override
public boolean areContentsTheSame(ItemEntity oldEntity,
ItemEntity newEntity) {
return oldEntity.equals(newEntity);
}
};
PagingItemRepository
public class PagingItemRepository {
private PagingItemDao itemDao;
LivePagedListBuilder<Integer, ItemEntity> builder;
public PagingItemRepository(PagingItemDao itemDao) {
this.itemDao = itemDao;
DataSource.Factory<Integer, ItemEntity> factory = itemDao.getAllItems();
PagedList.Config config = new PagedList.Config.Builder().
setPageSize(60).
setPrefetchDistance(0).
setEnablePlaceholders(true).
setInitialLoadSizeHint(120).
//setMaxSize(200).
build();
builder = new LivePagedListBuilder<>(factory, config);
builder.setBoundaryCallback(new MyBoundaryCallback(itemDao));
}
LiveData<PagedList<ItemEntity>> getAllItems() {
return builder.build();
}
}
MyBoundaryCallback
public static class MyBoundaryCallback extends PagedList.BoundaryCallback<ItemEntity> {
private PagingItemDao itemDao;
public MyBoundaryCallback(PagingItemDao itemDao) {
this.itemDao = itemDao;
}
@Override
public void onZeroItemsLoaded() {
new Thread(new Runnable() {
@Override
public void run() {
final List<ItemEntity> entities = new ArrayList<>();
for (int i = 0; i < 30; i++) {
count++;
ItemEntity entity = new ItemEntity();
entity.setText(count + "");
entities.add(entity);
}
itemDao.addItems(entities);
}
}).start();
}
@Override
public void onItemAtFrontLoaded(@NonNull ItemEntity itemAtFront) {
}
@Override
public void onItemAtEndLoaded(@NonNull ItemEntity itemAtEnd) {
final Long id = itemAtEnd.getId();
new Thread(new Runnable() {
@Override
public void run() {
if (id >= 530) {
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
final List<ItemEntity> entities = new ArrayList<>();
for (int i = 0; i < 50; i++) {
count++;
ItemEntity entity = new ItemEntity();
entity.setText(count + "");
entities.add(entity);
}
itemDao.addItems(entities);
}
}).start();
}
}
PagingItemDao
@Dao
public interface PagingItemDao {
@Query("select * from item")
DataSource.Factory<Integer, ItemEntity> getAllItems();
@Insert
void addItems(List<ItemEntity> entities);
@Query("delete from item")
void delete();
}