Android - 改造分页

时间:2015-09-16 00:51:05

标签: android pagination retrofit

使用Retrofit,在分页REST响应中加载“更多”数据的最佳方法是什么?

背景

我正在从AsyncTasks + Loaders迁移到Retrofit。与此相关SO question中的OP情况不同,我希望仅在请求时获取Retrofit获取数据,而不是一次下载所有项目。目前,当用户通过调用LoaderManager.restartLoader()滚动到当前列表视图页面的末尾时,可以很容易地执行此操作。

我们的客户消耗的API的示例响应:

{
  "data": [
    {
      "nid": 4382,
      "comment_text": "some user comment", ...
    }, ...
  ],
  "paging": {
    "nextPage": "http://api.domain.net/v2/comments?page=1&pageSize=20&requestLandmark=M4ewMnwxDUsdadf0NTIwfDU2OA==%3D%3D",
    "itemsTotal": 5164,
    "page": 0,
    "pagerMax": 218,
    "requestLandmark": "M4ewMnwxDUsdadf0NTIwfDU2OA=="
  }
}

我知道我们可以像这样向我们的APIService提供'page'参数:

public interface APIService {
  @GET("/comments/{page}") //
  List<Comment> getComments(@Path("page") int page);
}

然而,挑战在于我们还有许多其他端点,除了评论(用户故事,喜欢,趋势等)之外,还为我们提供了不同的数据列表,我们不想编写loadMore()方法如果有更好的替代方案,我们必须获取每个端点以获取其他页面。换句话说,为我们拥有的每个 GET请求/服务维护一个currentPageIndex是笨拙的,因为它会破坏托管列表视图的Fragment。 LoaderManager结构为我们整齐地工作,因为我们创建了一个包装类,它只是简单地接受相应列表视图的回调,因此无论数据模型类型如何,我们都有一个点来管理分页。也就是说,我们片段的回收视图onScroll听众看起来像这样:

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    ...
    mLoadHandler.handleNewItemLoading(firstVisibleItem, visibleItemCount, totalItemCount);
    ...
}

和mLoaderHandler是一个实例:

/**
 * Handles new content loading for ListView if the list has been scrolled to the end
 */
public class ListLoadMoreHandler {

    private static final int MAX_PAGES_TO_LOAD = 10; 
    private boolean mLoadingContent;
    private int mPageIndex = 0;
    private int mTotalItemCount;
    private final LoaderManager mLoaderManager;
    private final int mLoaderId;
    private final LoaderManager.LoaderCallbacks<?> mCallBack;

    public ListLoadMoreHandler(LoaderManager loaderManager,
                                  int loaderId,
                                  LoaderManager.LoaderCallbacks<?> callback) {
        mLoaderManager = loaderManager;
        mLoaderId = loaderId;
        mCallBack = callback;
    }

    /**
     * Trigger loading of new items when end of list view is reached
     * @param firstVisibleItem first visible item in list view
     * @param visibleItemCount visible items in list view
     * @param totalItemCount total items in list view
     */
    public void handleNewItemLoading(int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if (totalItemCount == 0 || totalItemCount < RestClient.DEFAULT_PAGINATION_SIZE) {
            return;
        }

        int visibleTrigger = 2;
        if (mPageIndex < MAX_PAGES_TO_LOAD && !mLoadingContent &&
                (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleTrigger)) {
            Log.d(TAG, "restarting loader");
            mLoadingContent = true;
            mPageIndex++;
            mLoaderManager.restartLoader(mLoaderId, null, mCallBack);
        }
    }
    ...
}

有关如何编写可扩展,符合改进标准版本的ListLoadMoreHandler的任何建议?

0 个答案:

没有答案