目录
1.Paging2.x
(1)使用
javabean:
public class Person {
private String id;
private String name;
private String sex;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
return getId().equals(person.getId()) &&
getName().equals(person.getName()) &&
getSex().equals(person.getSex());
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public int hashCode() {
return Objects.hash(getId(), getName(), getSex());
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
ViewModel
public class PersonViewModel extends ViewModel {
private final LiveData<PagedList<Person>> pagedListLiveData;
public PersonViewModel() {
// @1 Factory 的创建
DataSource.Factory<Integer, Person> factory = new PersonDataSourceFactory();
/*PagedList.Config pConfig = new PagedList.Config.Builder()
.setPageSize(20)
.setEnablePlaceholders(true)
.setInitialLoadSizeHint(20)
.build();*/
// @1 Factory
pagedListLiveData = new LivePagedListBuilder<Integer, Person>(factory,
new PagedList.Config.Builder()
.setEnablePlaceholders(true)
.setPageSize(20)
.build()).build();
}
public LiveData<PagedList<Person>> getPagedListLiveData() {
return pagedListLiveData;
}
}
Adapter
public class RecyclerPagingAdapter extends PagedListAdapter<Person, RecyclerPagingAdapter.MyRecyclerViewHolder> {
//需要oldPerson与新 newPerson 比较才能得出变化的数据
private static DiffUtil.ItemCallback<Person> DIFF_STUDENT =
new DiffUtil.ItemCallback<Person>() {
// 判断Item是否已经存在
@Override
public boolean areItemsTheSame(Person oldPerson, Person newPerson) {
return oldPerson.getId().equals(newPerson.getId());
}
// 如果Item已经存在则会调用此方法,判断Item的内容是否一致
@Override
public boolean areContentsTheSame(Person oldPerson, Person newPerson) {
return oldPerson.equals(newPerson);
}
};
protected RecyclerPagingAdapter() {
super(DIFF_STUDENT);
}
......
}
Factory
public class PersonDataSourceFactory extends DataSource.Factory<Integer, Person> {
@NonNull
@Override
public DataSource<Integer, Person> create() {
return new CustomPageDataSource(new DataRepository());
}
}
public class CustomPageDataSource extends PageKeyedDataSource<Integer, Person> {
private DataRepository dataRepository;
CustomPageDataSource(DataRepository dataRepository) {
this.dataRepository = dataRepository;
}
// loadInitial 初始加载数据
@Override
public void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Integer, Person> callback) {
List<Person> dataList = dataRepository.initData(params.requestedLoadSize);
callback.onResult(dataList, null, 2);
}
// loadBefore 向前分页加载数据
@Override
public void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, Person> callback) {
List<Person> dataList = dataRepository.loadPageData(params.key, params.requestedLoadSize);
if (dataList != null) {
callback.onResult(dataList, params.key - 1);
}
}
// loadAfter 向后分页加载数据
@Override
public void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, Person> callback) {
List<Person> dataList = dataRepository.loadPageData(params.key, params.requestedLoadSize);
if (dataList != null) {
callback.onResult(dataList, params.key + 1);
}
}
}
仓库类
public class DataRepository {
private List<Person> dataList = new ArrayList<>();
public DataRepository() {
for (int i = 0; i < 1000; i++) {
Person person = new Person();
person.setId("ID号是:" + i);
person.setName("我名称:" + i);
person.setSex("我性别:" + i);
dataList.add(person);
}
}
public List<Person> initData(int size) {
return dataList.subList(0, size);
}
public List<Person> loadPageData(int page, int size) {
int totalPage;
if (dataList.size() % size == 0) {
totalPage = dataList.size() / size;
} else {
totalPage = dataList.size() / size + 1;
}
if (page > totalPage || page < 1) {
return null;
}
if (page == totalPage) {
return dataList.subList((page - 1) * size, dataList.size());
}
return dataList.subList((page - 1) * size, page * size);
}
}
activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycle_view);
recyclerPagingAdapter = new RecyclerPagingAdapter();
personViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(PersonViewModel.class);
personViewModel.getPagedListLiveData().observe(this, new Observer<PagedList<Person>>() {
@Override
public void onChanged(PagedList<Person> persons) {
recyclerPagingAdapter.submitList(persons);
}
});
recyclerView.setAdapter(recyclerPagingAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
这样我们就做到了自动分页,自动请求网络请求刷新UI。
(2)源码分析
【1】初次如何加载数据
首先咱们从入口出发,我们在activity获取了viewmodel的livedata进行订阅。咱们就从viewmodel出发。看到了在viewmodel中通过LivePagedListBuilder建造者模式创建出来的livedata。
public LiveData<PagedList<Value>> build() {
return create(mInitialLoadKey, mConfig, mBoundaryCallback, mDataSourceFactory,
ArchTaskExecutor.getMainThreadExecutor(), mFetchExecutor);
}
@SuppressLint("RestrictedApi")
private static <Key, Value> LiveData<PagedList<Value>> create(
@Nullable final Key initialLoadKey,
@NonNull final PagedList.Config config,
@Nullable final PagedList.BoundaryCallback boundaryCallback,
@NonNull final DataSource.Factory<Key, Value> dataSourceFactory,
@NonNull final Executor notifyExecutor,
@NonNull final Executor fetchExecutor) {
return new ComputableLiveData<PagedList<Value>>(fetchExecutor) {
@Nullable
private PagedList<Value> mList;
@Nullable
private DataSource<Key, Value> mDataSource;
private final DataSource.InvalidatedCallback mCallback =
new DataSource.InvalidatedCallback() {
@Override
public void onInvalidated() {
invalidate();
}
};
......
}.getLiveData();
}
他的建造者模式通过源码我们看到她给我们创建了一个ComputableLiveData的类。那具体实现我们就要去其内部看看。
public ComputableLiveData(@NonNull Executor executor) {
mExecutor = executor;//默认咱们传过来的是IO
//创建一个livedata,当它所订阅的生命组件到达活跃状态时会触发
mLiveData = new LiveData<T>() {
@Override
protected void onActive() {
mExecutor.execute(mRefreshRunnable);
}
};
}
//返回构造方法里初始化的livedata
public LiveData<T> getLiveData() {
return mLiveData;
}
final Runnable mRefreshRunnable = new Runnable() {
@WorkerThread
@Override
public void run() {
boolean computed;
do {
computed = false;
//通过CAS自旋来判断值
//当初次时会满足条件
if (mComputing.compareAndSet(false, true)) {
try {
T value = null;
//当初次时会满足条件
while (mInvalid.compareAndSet(true, false)) {
computed = true;
//计算值
value = compute();
}
if (computed) {
//由于咱们传过来的是IO线程,所以用postValue进行传值
//这边livedata一传值,就会触发我们activity的订阅就会向adapter执行submitList,进行数据更新
mLiveData.postValue(value);
}
} finally {
mComputing.set(false);
}
}
} while (computed && mInvalid.get());
}
};
那首次数据进行改变咱们看到这边就大概明白了,但是它compute都做了些啥,咱们不知道。compute方法在我们之前返回的ComputableLiveData类中有实现。
@override
protected PagedList<Value> compute() {
@Nullable Key initializeKey = initialLoadKey;
if (mList != null) {
initializeKey = (Key) mList.getLastKey();
}
do {
if (mDataSource != null) {
mDataSource.removeInvalidatedCallback(mCallback);
}
//获取咱们factory中create创建的数据源
mDataSource = dataSourceFactory.create();
mDataSource.addInvalidatedCallback(mCallback);
//我们传过来的参数,几乎都在此被这个类构建使用
mList = new PagedList.Builder<>(mDataSource, config)
.setNotifyExecutor(notifyExecutor)//Main线程
.setFetchExecutor(fetchExecutor)//IO线程
.setBoundaryCallback(boundaryCallback)
.setInitialKey(initializeKey)
.build();
} while (mList.isDetached());
return mList;
}
看到参数几乎都用于构建PagedList,看看内部
public PagedList<Value> build() {
if (mNotifyExecutor == null) {
throw new IllegalArgumentException("MainThreadExecutor required");
}
if (mFetchExecutor == null) {
throw new IllegalArgumentException("BackgroundThreadExecutor required");
}
return PagedList.create(
mDataSource,
mNotifyExecutor,
mFetchExecutor,
mBoundaryCallback,
mConfig,
mInitialKey);
}
static <K, T> PagedList<T> create(@NonNull DataSource<K, T> dataSource,
@NonNull Executor notifyExecutor,
@NonNull Executor fetchExecutor,
@Nullable BoundaryCallback<T> boundaryCallback,
@NonNull Config config,
@Nullable K key) {
//判断源是否连续 || 是否存在占位
if (dataSource.isContiguous() || !config.enablePlaceholders) {
int lastLoad = ContiguousPagedList.LAST_LOAD_UNSPECIFIED;
//不存在占位 且 源不连续
if (!dataSource.isContiguous()) {
//创建单源PositionalDataSource
dataSource = (DataSource<K, T>) ((PositionalDataSource<T>) dataSource)
.wrapAsContiguousWithoutPlaceholders();
if (key != null) {
lastLoad = (Integer) key;
}
}
ContiguousDataSource<K, T> contigDataSource = (ContiguousDataSource<K, T>) dataSource;
//创建ContiguousPagedList实例
return new ContiguousPagedList<>(contigDataSource,
notifyExecutor,
fetchExecutor,
boundaryCallback,
config,
key,
lastLoad);
} else {
return new TiledPagedList<>((PositionalDataSource<T>) dataSource,
notifyExecutor,
fetchExecutor,
boundaryCallback,
config,
(key != null) ? (Integer) key : 0);
}
}
我们以连续源为例,ContiguousPagedList继续看。
ContiguousPagedList(
@NonNull ContiguousDataSource<K, V> dataSource,
@NonNull Executor mainThreadExecutor,
@NonNull Executor backgroundThreadExecutor,
@Nullable BoundaryCallback<V> boundaryCallback,
@NonNull Config config,
final @Nullable K key,
int lastLoad) {
super(new PagedStorage<V>(), mainThreadExecutor, backgroundThreadExecutor,
boundaryCallback, config);
mDataSource = dataSource;
mLastLoad = lastLoad;
//判断数据源是否失效
if (mDataSource.isInvalid()) {
detach();
} else {
//初始化加载
mDataSource.dispatchLoadInitial(key,
mConfig.initialLoadSizeHint,
mConfig.pageSize,
mConfig.enablePlaceholders,
mMainThreadExecutor,
mReceiver);
}
mShouldTrim = mDataSource.supportsPageDropping()
&& mConfig.maxSize != Config.MAX_SIZE_UNBOUNDED;
}
到这咱们就到了初始化加载数据了,看它的内部是个抽象类。我们的例子以PageKeyedDataSource为例。
@Override
final void dispatchLoadInitial(@Nullable Key key, int initialLoadSize, int pageSize,
boolean enablePlaceholders, @NonNull Executor mainThreadExecutor,
@NonNull PageResult.Receiver<Value> receiver) {
LoadInitialCallbackImpl<Key, Value> callback =
new LoadInitialCallbackImpl<>(this, enablePlaceholders, receiver);//(1)创建了一个回调
loadInitial(new LoadInitialParams<Key>(initialLoadSize, enablePlaceholders), callback);//(2)真正加载数据的方法
callback.mCallbackHelper.setPostExecutor(mainThreadExecutor);//设置回调的线程为主线程
}
(1)
LoadInitialCallbackImpl(@NonNull PageKeyedDataSource<Key, Value> dataSource, boolean countingEnabled, @NonNull PageResult.Receiver<Value> receiver) { mCallbackHelper = new LoadCallbackHelper<>( dataSource, PageResult.INIT, null, receiver);//设置状态为INIT mDataSource = dataSource; mCountingEnabled = countingEnabled; }
(2)loadInitial是我们实现的DataSource中实现的方法
@Override public void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Integer, Person> callback) { //在这里我们就进行网络请求数据了 List<Person> dataList = dataRepository.initData(params.requestedLoadSize); //调用回调的onResult callback.onResult(dataList, null, 2); }
到这,咱们就跑到了LoadInitialCallback.onResult方法里了。
public void onResult(@NonNull List<Value> data, @Nullable Key previousPageKey,
@Nullable Key nextPageKey) {
if (!mCallbackHelper.dispatchInvalidResultIfInvalid()) {
//key值赋值
mDataSource.initKeys(previousPageKey, nextPageKey);
//主要分发结果
mCallbackHelper.dispatchResultToReceiver(new PageResult<>(data, 0, 0, 0));
}
}
//判断是否有效
boolean dispatchInvalidResultIfInvalid() {
if (mDataSource.isInvalid()) {
dispatchResultToReceiver(PageResult.<T>getInvalidResult());
return true;
}
return false;
}
void dispatchResultToReceiver(final @NonNull PageResult<T> result) {
Executor executor;
synchronized (mSignalLock) {
if (mHasSignalled) {
throw new IllegalStateException(
"callback.onResult already called, cannot call again.");
}
mHasSignalled = true;
executor = mPostExecutor;//主线程
}
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
//计算页面结果,mReceiver在ContiguousPagedList类中为成员变量
mReceiver.onPageResult(mResultType, result);
}
});
} else {
mReceiver.onPageResult(mResultType, result);
}
}
最终执行了onPageResult
public void onPageResult(@PageResult.ResultType int resultType,
@NonNull PageResult<V> pageResult) {
......
List<V> page = pageResult.page;
if (resultType == PageResult.INIT) {
//状态为初始化时执行
mStorage.init(pageResult.leadingNulls, page, pageResult.trailingNulls,
pageResult.positionOffset, ContiguousPagedList.this);
if (mLastLoad == LAST_LOAD_UNSPECIFIED) {
mLastLoad =
pageResult.leadingNulls + pageResult.positionOffset + page.size() / 2;
}
} else {
boolean trimFromFront = mLastLoad > mStorage.getMiddleOfLoadedRange();
boolean skipNewPage = mShouldTrim
&& mStorage.shouldPreTrimNewPage(
mConfig.maxSize, mRequiredRemainder, page.size());
if (resultType == PageResult.APPEND) {
//状态为追加页面
if (skipNewPage && !trimFromFront) {
//没有增加任何数据
mAppendItemsRequested = 0;
mAppendWorkerState = READY_TO_FETCH;
} else {
//主要执行
mStorage.appendPage(page, ContiguousPagedList.this);
}
} else if (resultType == PageResult.PREPEND) {
if (skipNewPage && trimFromFront) {
//没有增加任何数据
mPrependItemsRequested = 0;
mPrependWorkerState = READY_TO_FETCH;
} else {
//主要执行
mStorage.prependPage(page, ContiguousPagedList.this);
}
} else {
throw new IllegalArgumentException("unexpected resultType " + resultType);
}
......
}
可以看到主要处理就在这边的onPageResult方法,调用了Storage进行我们的初始化、往后追加页面和向前追加页面。我们先看init。初始化整个流程还没走完。
//PagedStorage中的方法
void init(int leadingNulls, @NonNull List<T> page, int trailingNulls, int positionOffset,
@NonNull Callback callback) {
init(leadingNulls, page, trailingNulls, positionOffset);
callback.onInitialized(size());
}
//ContiguousPagedList中的方法
public void onInitialized(int count) {
notifyInserted(0, count);
// simple heuristic to decide if, when dropping pages, we should replace with placeholders
mReplacePagesWithNulls =
mStorage.getLeadingNullCount() > 0 || mStorage.getTrailingNullCount() > 0;
}
//PagedList中的方法
void notifyInserted(int position, int count) {
//由于我们初始化,所以当前mCallback中还没有存在任何的回调,所以无法通过回调去执行更新插入
if (count != 0) {
for (int i = mCallbacks.size() - 1; i >= 0; i--) {
final Callback callback = mCallbacks.get(i).get();
if (callback != null) {
callback.onInserted(position, count);
}
}
}
}
到这我们compute一路走下来就完全走完了,一路上我们通过factory创建了对应的dataSource,通过dataSource请求数据之后,进行了storage的初始化。最后就执行了livedata.postValue进行初次的传值。(当然如果创建了BoundaryCallback也会对应执行)。数据进行了改变,熟悉livedata就直到会走到我们activity中的observer方法里了。
【2】初次刷新UI
personViewModel.getPagedListLiveData().observe(this, new Observer<PagedList<Person>>() {
@Override
public void onChanged(PagedList<Person> persons) {
recyclerPagingAdapter.submitList(persons);//提交数据入口
}
});
//我们在adapter中创建的callback
protected PagedListAdapter(@NonNull DiffUtil.ItemCallback<T> diffCallback) {
mDiffer = new AsyncPagedListDiffer<>(this, diffCallback);
mDiffer.addPagedListListener(mListener);
}
public void submitList(@Nullable PagedList<T> pagedList) {
mDiffer.submitList(pagedList);
}
public AsyncPagedListDiffer(@NonNull RecyclerView.Adapter adapter,
@NonNull DiffUtil.ItemCallback<T> diffCallback) {
mUpdateCallback = new AdapterListUpdateCallback(adapter);
mConfig = new AsyncDifferConfig.Builder<>(diffCallback).build();
}
public void submitList(@Nullable final PagedList<T> pagedList) {
submitList(pagedList, null);
}
public void submitList(@Nullable final PagedList<T> pagedList,
@Nullable final Runnable commitCallback) {
......
final PagedList<T> previous = (mSnapshot != null) ? mSnapshot : mPagedList;
if (pagedList == null) {
int removedCount = getItemCount();
if (mPagedList != null) {
mPagedList.removeWeakCallback(mPagedListCallback);
mPagedList = null;
} else if (mSnapshot != null) {
mSnapshot = null;
}
mUpdateCallback.onRemoved(0, removedCount);
onCurrentListChanged(previous, null, commitCallback);
return;
}
if (mPagedList == null && mSnapshot == null) {
//上一页数据为空 且 快照不存在
mPagedList = pagedList;
//之前说初始化所以mCallback为空,到这里向我们mCallback存回调
pagedList.addWeakCallback(null, mPagedListCallback);
//真正的刷新
mUpdateCallback.onInserted(0, pagedList.size());
onCurrentListChanged(null, pagedList, commitCallback);
return;
}
......
}
private final RecyclerView.Adapter mAdapter;
public AdapterListUpdateCallback(@NonNull RecyclerView.Adapter adapter) {
mAdapter = adapter;
}
@Override
public void onInserted(int position, int count) {
mAdapter.notifyItemRangeInserted(position, count);
}
到此为止,咱们的刷新UI就结束了,但是我们仔细看它是如何对adapter进行修改的。我们类实现自PagedListAdapter,看看它怎么存我们数据的。
@Nullable
protected T getItem(int position) {
return mDiffer.getItem(position);
}
@Override
public int getItemCount() {
return mDiffer.getItemCount();
}
public int getItemCount() {
if (mPagedList != null) {
return mPagedList.size();
}
return mSnapshot == null ? 0 : mSnapshot.size();
}
public T getItem(int index) {
if (mPagedList == null) {
if (mSnapshot == null) {
throw new IndexOutOfBoundsException(
"Item count is zero, getItem() call is invalid");
} else {
return mSnapshot.get(index);
}
}
mPagedList.loadAround(index);
return mPagedList.get(index);//从数据列表中获取数据
}
到这,首次刷新UI大家就能了解了,数据传递在AsyncPagedListDiffer此类中,有多少数据找它拿,然后我们在我们些的adapter的onBindViewHolder方法直接获取对应实例,直接赋值给控件即可。
【3】后续的追加页面
我们并写代码主动的追加,它是怎么实现的呢。其实看到刚才的getItem我们就已经看到了,它在获取Item时有调用PagedList的方法。
public void loadAround(int index) {
if (index < 0 || index >= size()) {
//当前下标越界判断
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size());
}
mLastLoad = index + getPositionOffset();
//主要加载方法
loadAroundInternal(index);
mLowestIndexAccessed = Math.min(mLowestIndexAccessed, index);
mHighestIndexAccessed = Math.max(mHighestIndexAccessed, index);
tryDispatchBoundaryCallbacks(true);
}
执行了loadAroundInternal方法,我们这是以连续源为例的,所以我们去ContiguousPagedList看
protected void loadAroundInternal(int index) {
int prependItems = getPrependItemsRequested(mConfig.prefetchDistance, index,
mStorage.getLeadingNullCount());
int appendItems = getAppendItemsRequested(mConfig.prefetchDistance, index,
mStorage.getLeadingNullCount() + mStorage.getStorageCount());
mPrependItemsRequested = Math.max(prependItems, mPrependItemsRequested);
//判断是否为向前追加
if (mPrependItemsRequested > 0) {
schedulePrepend();
}
mAppendItemsRequested = Math.max(appendItems, mAppendItemsRequested);
//判断是否为向后追加
if (mAppendItemsRequested > 0) {
scheduleAppend();
}
}
我们这边就以往后追加看
private void scheduleAppend() {
if (mAppendWorkerState != READY_TO_FETCH) {
return;
}
mAppendWorkerState = FETCHING;
final int position = mStorage.getLeadingNullCount()
+ mStorage.getStorageCount() - 1 + mStorage.getPositionOffset();
final V item = mStorage.getLastLoadedItem();
mBackgroundThreadExecutor.execute(new Runnable() {
@Override
public void run() {
if (isDetached()) {
return;
}
if (mDataSource.isInvalid()) {
detach();
} else {
//执行向后请求方法
mDataSource.dispatchLoadAfter(position, item, mConfig.pageSize,
mMainThreadExecutor, mReceiver);
}
}
});
}
@Override
final void dispatchLoadAfter(int currentEndIndex, @NonNull Value currentEndItem,
int pageSize, @NonNull Executor mainThreadExecutor,
@NonNull PageResult.Receiver<Value> receiver) {
@Nullable Key key = getNextKey();
if (key != null) {
//这里就直接调用了自己实现的DataSource的loadAfter方法,给LoadCallbackImpl设置状态为APPEND
loadAfter(new LoadParams<>(key, pageSize),
new LoadCallbackImpl<>(this, PageResult.APPEND, mainThreadExecutor, receiver));
} else {
receiver.onPageResult(PageResult.APPEND, PageResult.<Value>getEmptyResult());
}
}
@Override
public void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, Person> callback) {
List<Person> dataList = dataRepository.loadPageData(params.key, params.requestedLoadSize);
if (dataList != null) {
//数据交给回调
callback.onResult(dataList, params.key + 1);
}
}
@Override
public void onResult(@NonNull List<Value> data, @Nullable Key adjacentPageKey) {
if (!mCallbackHelper.dispatchInvalidResultIfInvalid()) {
//判断type是往前追加,还是往后追加,设置对应的key
if (mCallbackHelper.mResultType == PageResult.APPEND) {
mDataSource.setNextKey(adjacentPageKey);
} else {
mDataSource.setPreviousKey(adjacentPageKey);
}
//最终还是调用到了dispatchResultToReceiver这个方法
mCallbackHelper.dispatchResultToReceiver(new PageResult<>(data, 0, 0, 0));
}
}
最后还是调用到了咱们的dispatchResultToReceiver方法,后续方法就不粘了,直接粘onPageResult方法。
public void onPageResult(@PageResult.ResultType int resultType,
@NonNull PageResult<V> pageResult) {
......
List<V> page = pageResult.page;
if (resultType == PageResult.INIT) {
......
} else {
boolean trimFromFront = mLastLoad > mStorage.getMiddleOfLoadedRange();
boolean skipNewPage = mShouldTrim
&& mStorage.shouldPreTrimNewPage(
mConfig.maxSize, mRequiredRemainder, page.size());
if (resultType == PageResult.APPEND) {
//状态为追加页面
if (skipNewPage && !trimFromFront) {
//没有增加任何数据
mAppendItemsRequested = 0;
mAppendWorkerState = READY_TO_FETCH;
} else {
//主要执行
mStorage.appendPage(page, ContiguousPagedList.this);
}
} else if (resultType == PageResult.PREPEND) {
if (skipNewPage && trimFromFront) {
//没有增加任何数据
mPrependItemsRequested = 0;
mPrependWorkerState = READY_TO_FETCH;
} else {
//主要执行
mStorage.prependPage(page, ContiguousPagedList.this);
}
} else {
throw new IllegalArgumentException("unexpected resultType " + resultType);
}
......
}
void appendPage(@NonNull List<T> page, @NonNull Callback callback) {
final int count = page.size();
......
mPages.add(page);
mLoadedCount += count;
mStorageCount += count;
final int changedCount = Math.min(mTrailingNullCount, count);
final int addedCount = count - changedCount;
if (changedCount != 0) {
mTrailingNullCount -= changedCount;
}
mNumberAppended += count;
callback.onPageAppended(mLeadingNullCount + mStorageCount - count,
changedCount, addedCount);
}
public void onPageAppended(int endPosition, int changedCount, int addedCount) {
// consider whether to post more work, now that a page is fully appended
mAppendItemsRequested = mAppendItemsRequested - changedCount - addedCount;
mAppendWorkerState = READY_TO_FETCH;
if (mAppendItemsRequested > 0) {
// not done appending, keep going
scheduleAppend();
}
// finally dispatch callbacks, after append may have already been scheduled
notifyChanged(endPosition, changedCount);
notifyInserted(endPosition + changedCount, addedCount);
}
这样就去刷新我们的数据了。但是我自己看的时候有疑问,后续的刷新啥时候有改动到mPagedList的大小。于是我跑到PagedList中看了这些方法。
@Override
public int size() {
return mStorage.size();
}
public List<T> snapshot() {
if (isImmutable()) {
return this;
}
return new SnapshotPagedList<>(this);
}
@Override
@Nullable
public T get(int index) {
T item = mStorage.get(index);
if (item != null) {
mLastItem = item;
}
return item;
}
数据它是存储在storage中的,所以这样我们就闭合了。
总结:2.x-首先我们构建了一个LiveData然后在订阅的生命周期组件到达活跃时会触发去计算,计算中会通过我们实现的factory去创建我们的dataSource。接着创建PagedList中会执行我们dataSource的初始化请求,请求完毕后初始化storage,将数据存储。到此初始化和请求接口就走完了。然后postValue将我们的数据传递,主要实现是在父类的成员变量mDiffer中。adapter数据从这取。我们的数据存自storage。后续的追加页面由getItem来触发,后续数据增加storage的数据会改变,然后在通知adapter刷新。