赞
踩
目录
1.Paging2.x
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 + '\'' +
- '}';
- }
- }

- 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。
首先咱们从入口出发,我们在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方法里了。
- 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方法直接获取对应实例,直接赋值给控件即可。
我们并写代码主动的追加,它是怎么实现的呢。其实看到刚才的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刷新。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。