使用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的任何建议?