Android 无休止滚动时分页库何时请求更多项目

Android Paging Library when to request more items when doing an endless scrolling

如何使用新的 android Paging Library 架构组件知道何时向服务器请求更多项目?例如,如果我想实现从服务器加载数据的无限滚动,我如何知道何时必须请求更多项目。

我使用下一个 class 来实现此功能:

package com.mlsdev.enjoymusic.data.repository;

import android.arch.paging.DataSource;
import android.arch.paging.TiledDataSource;
import android.arch.persistence.room.InvalidationTracker;
import android.support.annotation.NonNull;
import android.support.annotation.WorkerThread;
import android.util.Log;

import com.mlsdev.enjoymusic.data.local.DeezerDatabase;
import com.mlsdev.enjoymusic.data.local.Table;

import java.io.IOException;
import java.util.List;
import java.util.Set;

import retrofit2.Call;
import retrofit2.Response;

/**
 * Created by stafievsky on 09.10.17.
 */

public abstract class PagedNetworkBoundResource<ResultType, RequestType> extends TiledDataSource<ResultType> {

    private final InvalidationTracker.Observer mObserver;
    private DeezerDatabase db;

    public PagedNetworkBoundResource(DeezerDatabase db) {
        this.db = db;
        mObserver = new InvalidationTracker.Observer(Table.States.PLAY_STATE) {

            public void onInvalidated(@NonNull Set<String> tables) {
                invalidate();
            }
        };
        this.db.getInvalidationTracker().addWeakObserver(mObserver);
    }


    @Override
    public boolean isInvalid() {
        db.getInvalidationTracker().refreshVersionsSync();
        return super.isInvalid();
    }

    @Override
    public int countItems() {
        return DataSource.COUNT_UNDEFINED;
    }

    @Override
    public List<ResultType> loadRange(int startPosition, int count) {
        if (startPosition == 0 && count == 20) {
            clearDB();
        }
        fetchFromNetwork(startPosition, count);
        return loadFromDb(startPosition, count);
    }

    public abstract void clearDB();

    @WorkerThread
    private void fetchFromNetwork(int startPosition, int count) {
        if (createCall(startPosition, count) != null)
            try {
                Response<RequestType> response = createCall(startPosition, count).execute();
                if (response.isSuccessful() && response.code() == 200) {
                    saveCallResult(response.body());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

    @WorkerThread
    protected abstract void saveCallResult(@NonNull RequestType item);


    @WorkerThread
    protected abstract List<ResultType> loadFromDb(int startPosition, int count);

    @WorkerThread
    protected abstract Call<RequestType> createCall(int startPosition, int count);
}

以及此 class 的实现:

public LiveData<PagedList<ChartAlbumDao.Album>> getAlbums() {

    return new LivePagedListProvider<Integer, ChartAlbumDao.Album>() {
        @Override
        protected DataSource<Integer, ChartAlbumDao.Album> createDataSource() {
            return new PagedNetworkBoundResource<ChartAlbumDao.Album, ModelList<ChartAlbumEntity>>(db) {

                @Override
                public void clearDB() {

                }

                @Override
                protected void saveCallResult(@NonNull ModelList<ChartAlbumEntity> item) {
                    if (item != null) {
                        chartAlbumDao.saveAlbums(item.getItems());
                    }
                }

                @NonNull
                @Override
                protected List<ChartAlbumDao.Album> loadFromDb(int startPosition, int count) {
                    return chartAlbumDao.loadAlbums(count, startPosition);
                }

                @NonNull
                @Override
                protected Call<ModelList<ChartAlbumEntity>> createCall(int startPosition, int count) {
                    return deezerService.getChartAlbums(startPosition, count);
                }
            };
        }

    }.create(0, new PagedList.Config.Builder()
            .setEnablePlaceholders(false)
            .setPageSize(20)
            .setInitialLoadSizeHint(20)
            .build());
}