Yas*_*svi 5 android android-recyclerview android-architecture-components android-jetpack android-paging
我已经在我的应用程序中集成了分页组件,它的工作非常好(几乎).我有数据库+网络模型.数据库最初有一些消耗的项目LivePagedListBuilder
.我观察到这一点LiveData<PagedList<InboxEntity>>
并最终将列表提供给PagedListAdapter#submitList(PagedList<T> pagedList)
,例如:
LiveData<PagedList<Entity>> entities;
PagedList.Config pagedListConfig =
(new PagedList.Config.Builder()).setEnablePlaceholders(true)
.setPrefetchDistance(5)
.setEnablePlaceholders(false)
.setPageSize(10)
.setInitialLoadSizeHint(10)
.build();
entities = new LivePagedListBuilder<>(DAO.getItemList(), pagedListConfig)
entities.observe(this, new Observer<PagedList<Entity>>() {
@Override
public void onChanged(@Nullable PagedList<Entity> inboxEntities) {
inboxAdapter.submitList(inboxEntities);
isFirstLoad = false;
}
});
Run Code Online (Sandbox Code Playgroud)
DAO#getItemList
回报DataSource.Factory<Integer, Entity>
.
我正在侦听边界回调并在到达分页列表末尾时触发网络呼叫.该调用再次填充数据库.
还有一件事.我已AdapterDataObserver
在循环器视图上注册,因为如果在开头插入了一个项目,我将滚动到顶部位置:
RecyclerView.AdapterDataObserver adapterDataObserver = new RecyclerView.AdapterDataObserver() {
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
if (positionStart == 0) {
layoutManager.scrollToPositionWithOffset(positionStart, 0);
}
}
};
Run Code Online (Sandbox Code Playgroud)
我在这个模型中面临一个问题:
进行网络调用后,再次填充数据库并onChanged
使用new调用函数PagedList<Entity>
.现在,此分页列表是否仅包含新项目.我已经证实了这一点.
但onItemRangeInserted
方法被调用positionStart
为0
过,这表明被插入在一开始的项目.但他们不是.它们被插入到最后,由stetho db检查员确认.
那么,为什么是onItemRangeInserted
被调用positionStart
的0
?这使我难以区分何时在适配器的开头插入新物品以及何时插入物品.
编辑:
value itemCount
是10,这是我的页面大小.
在DiffCallback中,我只是比较areItemsTheSame
函数中两个实体的主键列.
我就是这样做的,虽然不理想,但很有效。我正在使用回收器视图,并将反向设置为 true,因为它是一个聊天应用程序,因此您必须根据您的用例进行调整。
在您的片段中创建一个计时器字段:
private Timer mTimer;
Run Code Online (Sandbox Code Playgroud)
添加一个滚动状态监听器,设置一个“最新行 ID”,您可以稍后进行比较。
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
//Get the latest id when we started scrolling
AppExecutors.getInstance().databaseIO().execute(() ->
mLatestMessageId = mHomeViewModel.getMessageViewModel().getLatestMessageId(mOurUsername, mChatname));
}
}});
Run Code Online (Sandbox Code Playgroud)
当调用插入时,使用 AdapterDataObserver 启动一个新的计时器。
private RecyclerView.AdapterDataObserver mAdapterDataObserver = new RecyclerView.AdapterDataObserver() {
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
if (mTimer != null) {
mTimer.cancel();
}
mTimer = new Timer();
mTimer.schedule(new CheckNewMessageTimer(), 100);
}
};
Run Code Online (Sandbox Code Playgroud)
这是计时器类,如果插入了新项目,“最新行 ID”将在数据库中递增。如果我已经在底部,我只会滚动到底部,否则我只是更改我拥有的“滚动到底部”FAB 的颜色。
class CheckNewMessageTimer extends TimerTask {
@Override
public void run() {
if (newItemsAdded()) {
int firstItemPosition = mLinearLayoutManager.findFirstVisibleItemPosition();
boolean atBottom = firstItemPosition == 1;
SurespotLog.d(TAG, "CheckNewMessageTimer, firstItemPosition: %d, atBottom: %b", firstItemPosition, atBottom);
AppExecutors.getInstance().mainThread().execute(() -> {
if (atBottom) {
SurespotLog.d(TAG, "CheckNewMessageTimer, scrolling to bottom");
mListView.scrollToPosition(0);
}
else {
if (mFab != null) {
SurespotLog.d(TAG, "CheckNewMessageTimer, new message received but we're not scrolled to the bottom, turn the scroll button blue");
mFab.setBackgroundTintList(ColorStateList.valueOf(getResources().getColor(R.color.surespotBlue)));
}
}
});
}
}
private boolean newItemsAdded() {
int dbLatestMessageID = mHomeViewModel.getMessageViewModel().getLatestMessageId(mOurUsername, mChatname);
if (mLatestMessageId > 0 && dbLatestMessageID > mLatestMessageId) {
mLatestMessageId = dbLatestMessageID;
return true;
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1038 次 |
最近记录: |