Fragment系列(四)------RecyclerFragment之网络部分

来源:互联网 发布:网络监控网线传输距离 编辑:程序博客网 时间:2024/06/03 13:19

(注:由于手机号验证问题,n6323438的博文转移至此)
链接: https://github.com/qijitech/android-starter-kit

Fragment系列:
(一)View与Presenter
(二)NetworkFragment
(三)RecyclerFragment之UI部分
(四)RecyclerFragment之网络部分

上一篇文章讲到了UI部分, 这次来看看网络部分.

PaginatorEmitter

上一篇文章提到, 在buildFragConfig方法里, 会new 一个PaginatorEmitter, 先看看PaginatorEmitter

 public PaginatorEmitter(StarterFragConfig fragConfig, Action1<PaginatorEmitter<E>> onRequest) {    this.mFragConfig = fragConfig;    this.currentPage = fragConfig.getStartPage();    resetPaginatorKey();    this.onRequest = onRequest;    this.hasMoreData = true;    this.isLoading = true;  }

先看构造方法, 传入参数 (StarterFragConfig fragConfig, Action1<PaginatorEmitter<E>> onRequest) :
1: 把fragConfig保存起来, 内部变量currentPage等于fragConfig.getStartPage(),这个默认值是1
2: onRequest保存起来, 内部变量hasMoreData和isLoading设为true
3: 通过fragConfig判断是通过分页还是key获取数据, 这里涉及到2个内部变量:String firstPaginatorKey, nextPaginatorKey. 如果是分页, 这2个变量为currentPage; 如果是key, 那就为null
构造完成
等等,有个疑惑, 刚才内部变量isLoading设为true, 但我们并没有看到发起网络请求啊. 看看Fragment的onResume方法就明白了,

 @Override public void onResume() {    super.onResume();    if (isNotNull(mPaginatorEmitter) && !mPaginatorEmitter.requested()) {      getPresenter().request();    }  }

可以看出每次onResume的时候, 就会进行网络请求.

现在来看看PaginatorEmitter中重要的内部变量 ArrayList<E> requestedItems.
这个变量放的是:从第一个id/第一页开始, 网络请求获取到的所有数据.
在onResume里, 会调用paginatorEmitter.requested()来判断, 其实就是判断requestedItems是否为空, 如果为空,那就开始网络请求. 那么一开始的时候这个requestedItems肯定是空的, 所以在onResume里就会发起第一个网络请求了.

onSuccess

再来看Fragment的onSuccess:

 @Override public void onSuccess(PaginatorContract<E> paginatorContract) {    ArrayList<? extends Entity> items = paginatorContract.items();    if (mPaginatorEmitter.isFirstPage()) {      mAdapter.clear();    }    if (items == null) { // handle null      items = Lists.newArrayList();    }    mAdapter.appendAll(items);    mPaginatorEmitter.received(paginatorContract);    if (isNotNull(mPaginate)) {      mPaginate.setHasMoreDataToLoad(false);    }    if (isAdapterEmpty(mAdapter)) {      getContentPresenter().displayEmptyView();    } else {      getContentPresenter().displayContentView();    }  }

1 首先也是判断requestedItems是否为空, 如果为空, 说明是第一次获取, 就会把recyclerViewAdapter清空. (这个功能对应于下拉刷新, 因为下拉刷新肯定要把原来的数据清除). 然后把获取到的数据append进去.
2 然后调用mPaginatorEmitter.received(paginatorContract), (这个paginatorContract是对获取的数据的包装).
进去received方法: 先把isLoading设为false, 把paginatorContract保存起来, 然后判断paginatorContract是否为空, 如果为空, 说明已经获得全部数据了, hasMoreData设为false. 如果不为空, 再看如果hasMoreData本身是true, 还是true; 否则就要看获取到的数据等不等于perpage(分页大小), 来判断还有没有更多数据. 最后, 涉及到2个内部变量:firstPaginatorKey和nextPaginatorKey, firstPaginatorKey设为requestItems的第一个的id, nextPaginatorKey设为最后一个的id.这2个变量就是用在PaginatorPresenter的request方法的那2个参数.
总的来看, 这个received方法干了2件事:判断是否获取了全部数据和保存下一页从哪里开始的信息

3 mPaginate.setHasMoreDataToLoad(false) 这个方法的参数如果为true, 那就显示那个上拉加载更多的圈圈; 为false就隐藏.
4 最后判断现在的recyclerView是不是空的, 如果是空的, 就用contentPresenter显示emptyView.
onSuccess完成.

onError

再看onError:
1 调用mPaginatorEmitter.received(null), 这个表示已经获取全部数据
2 剩下的和onSuccess很类似, 这里就不说了.

上拉加载更多

接下来就要来看上拉加载更多的实现: 前面我们提到, 当recyclerView滑动到需要加载的位置时, 会调用isLoading和hasLoadedAllItems这2个方法来看要不要发起网络请求, 这2个方法在StarterRecyclerFragment实现的.
先看isLoading方法: 判断mPaginatorEmitter的isLoading 和 swipeRefreshLayout的isRefreshing, 只要其中一个满足, 就会返回true.
这个设计是为了解决 多次滑到底部导致发起多次重复的网络请求 这个问题.
再看hasLoadedAllItems方法: 判断mPaginatorEmitter的hasMoreData.
这2个方法都通过, 就到onLoadMore方法了, 经过一堆的双保险判断, 就会显示显示那个上拉加载更多的圈圈, 并发起网络请求.
上拉加载更多到此结束.

下拉刷新

下拉刷新其实就是SwipeRefreshLayout的onRefresh方法
源码比较简单, 就不贴了.
首先判断是否正在请求, 如果正在请求, 那就显示SwipeRefreshLayout自带的进度条.
如果不是, 那就重置PaginatorEmitter, 然后进行网络请求.

下一篇文章, 我会讲一下Presenter中是如何管理网络请求的.

阅读全文
0 0
原创粉丝点击