一、前言
最近在做一款应用,因为 api 涉及到分页的,所以选择用 RecyclerView + Paging 去做,能省去向下滚动时去处理加载下一页的数据的逻辑,Paging 会自动去加载下一页的内容,首页要做个 Banner, 所以把 Banner 作为 RecyclerView 的 头添加进去,可是添加后下面的数据加载完就会自动滚到下面去,如下图,一下拉刷新,加载完数据后就滚到下面去了
二、问题分析
当我去掉头部刷新,一切是正常的,
所以原因应该就是添加了 Header,导致 position 不准确, RecyclerView 不知道有 Header 的存在,一刷新插入、删除等操作是从 0 开始的,但 Header 在前面霸占着位置了(陈独秀同学在前面站着不坐下),所以插入、删除等操作不要动到 Header 的位置,使其操作正确的 position, 那怎么让其不去动到 Heasder 的位置呢?只有看看源码能不能找到解决的办法了, RecyclerView + Paging Library 用的 Adapter 用的是继承 PagedListAdapter 的,
PagedListAdapter 是使用了 DiffUtil 的,DiffUtil 里的插入、删除等操作是用到 AdapterListUpdateCallback 这个类
AdapterListUpdateCallback 这个类里插入、删除等操作调用的是 RecyclerView.Adapter mAdapter 的,
/**
* ListUpdateCallback that dispatches update events to the given adapter.
*
* @see DiffUtil.DiffResult#dispatchUpdatesTo(RecyclerView.Adapter)
*/
public final class AdapterListUpdateCallback implements ListUpdateCallback {
@NonNull
private final RecyclerView.Adapter mAdapter;
/**
* Creates an AdapterListUpdateCallback that will dispatch update events to the given adapter.
*
* @param adapter The Adapter to send updates to.
*/
public AdapterListUpdateCallback(@NonNull RecyclerView.Adapter adapter) {
mAdapter = adapter;
}
/** {@inheritDoc} */
@Override
public void onInserted(int position, int count) {
mAdapter.notifyItemRangeInserted(position, count);
}
/** {@inheritDoc} */
@Override
public void onRemoved(int position, int count) {
mAdapter.notifyItemRangeRemoved(position, count);
}
/** {@inheritDoc} */
@Override
public void onMoved(int fromPosition, int toPosition) {
mAdapter.notifyItemMoved(fromPosition, toPosition);
}
/** {@inheritDoc} */
@Override
public void onChanged(int position, int count, Object payload) {
mAdapter.notifyItemRangeChanged(position, count, payload);
}
}
RecyclerView.Adapter 里用的是 mObservable 的插入、删除等操作,
这个 mObservable 是 AdapterDataObservable 类型的,
AdapterDataObservable 是继承 Observable 的
static class AdapterDataObservable extends Observable<AdapterDataObserver> {
public boolean hasObservers() {
return !mObservers.isEmpty();
}
public void notifyChanged() {
// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
public void notifyItemRangeChanged(int positionStart, int itemCount) {
notifyItemRangeChanged(positionStart, itemCount, null);
}