结合 MultiType 实现加载更多

    • 摘要:MultiType是一个分发管理类,帮助我们轻松实现复杂布局.建议大家阅读源码,作者的思路并不复杂但很巧妙.下面附上主要源码:publicclassLoadMoreDelegate{privateItemsmItems;privateMultiTypeAdaptermMultiTypeAdapter;privateOnLoadMoreListenermOnLoadMoreListener;privateScrollListenermScrollListener;publicL

    • MultiType 是一个分发管理类,帮助我们轻松实现复杂布局.建议大家阅读源码,作者的思路并不复杂但很巧妙.


      下面附上主要源码:


      public class LoadMoreDelegate { 
      private Items mItems; 
      private MultiTypeAdapter mMultiTypeAdapter; 
      private OnLoadMoreListener mOnLoadMoreListener; 
      private ScrollListener mScrollListener; 

      public LoadMoreDelegate(MultiTypeAdapter multiTypeAdapter, Items items, OnLoadMoreListener onLoadMoreListener) { 
      mMultiTypeAdapter = multiTypeAdapter; 
      mItems = items; 
      this.mOnLoadMoreListener = onLoadMoreListener; 

      public void attach(RecyclerView recyclerView) { 
      LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); 
      mScrollListener = new ScrollListener(mMultiTypeAdapter, mItems, linearLayoutManager, mOnLoadMoreListener); 
      recyclerView.addOnScrollListener(mScrollListener); 

      public void loadMoreComplete() { 
      mScrollListener.setLoading(false); 

      public void addData(Items items) { 
      int originSize = mItems.size() - 1; 
      mItems.remove(originSize);//删除"加载更多" 
      mItems.addAll(items);//添加新数据 
      //从最后的位置插入新数据 
      mMultiTypeAdapter.notifyItemRangeInserted(originSize, items.size() - 1); 

      public interface OnLoadMoreListener { 
      void onLoadMore(); 

      private static class ScrollListener extends RecyclerView.OnScrollListener { 
      private final int size = 2; 
      private boolean mLoading = false; 
      private Items mItems; 
      private final LoadMore mLoadMore = new LoadMore(); 
      private LinearLayoutManager mLinearLayoutManager; 
      private OnLoadMoreListener mOnLoadMoreListener; 
      private MultiTypeAdapter mMultiTypeAdapter; 
      ScrollListener(MultiTypeAdapter multiTypeAdapter, Items datas, LinearLayoutManager linearLayoutManager, OnLoadMoreListener onLoadMoreListener) { 
      mItems = datas; 
      mMultiTypeAdapter = multiTypeAdapter; 
      this.mLinearLayoutManager = linearLayoutManager; 
      this.mOnLoadMoreListener = onLoadMoreListener; 

      @Override 
      public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 
      if (dy < 0) {//下滑忽略 
      return; 

      int totalNum = mLinearLayoutManager.getItemCount(); 
      int lastVisiblePosition = mLinearLayoutManager.findLastCompletelyVisibleItemPosition(); 
      if (!mLoading &;&; lastVisiblePosition == totalNum - size) {//最后可见的view的位置为倒数第size个,触发加载更多 
      mLoading = true; 
      mItems.add(mLoadMore); 
      mMultiTypeAdapter.notifyItemInserted(mItems.size() - 1); 
      mOnLoadMoreListener.onLoadMore(); 


      void setLoading(boolean loading) { 
      this.mLoading = loading; 



      这里提下有些加载更多只是简单的直接使用 notifyDataSetChanged() 方法,效率上我没有研究过,不敢说哪个效率更好,但至少 RecycleView 给我们提供的动画效果没有了,所以建议还是采用 notifyItemInserted().


      完整示例:multitypeloadmore


      public class PullUpTestActivity extends AppCompatActivity implements LoadMoreDelegate.OnLoadMoreListener { 
      private Items mItems = new Items(); 
      private LoadMoreDelegate mLoadMoreDelegate; 
      @Bind(R.id.show) 
      RecyclerView mShow; 

      @Override 
      protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_pull_up); 
      ButterKnife.bind(this); 
      for (int i = 0; i < 20; i++) { 
      mItems.add("data***" + i); 


      MultiTypeAdapter multiTypeAdapter = new MultiTypeAdapter(mItems); 
      multiTypeAdapter.register(String.class, new NormalViewProvider()); 
      multiTypeAdapter.register(LoadMore.class, new LoadMoreViewProvider()); 
      mShow.setLayoutManager(new LinearLayoutManager(this)); 
      mShow.setAdapter(multiTypeAdapter); 
      mLoadMoreDelegate = new LoadMoreDelegate(multiTypeAdapter, mItems, this); 
      mLoadMoreDelegate.attach(mShow); 

      @Override 
      public void onLoadMore() { 
      getMore(); 

      private void getMore() { 
      new Thread(new Runnable() { 
      @Override 
      public void run() { 
      try { 
      Thread.sleep(2000); 
      runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
      Items strings = new Items(); 
      for (int i = 0; i < 20; i++) { 
      strings.add("data***more" + i); 

      mLoadMoreDelegate.addData(strings); 
      mLoadMoreDelegate.loadMoreComplete(); 

      }); 
      } catch (InterruptedException e) { 
      e.printStackTrace(); 



      }).start(); 


      还有一点提一下,这样的必须需要滑动界面才可以触发加载更多,如果第一屏数据不超过一屏,将没法触发加载更多.但这样我认为是合理的,如果第一页数据的请求就不满一屏,所以后面应该是在没有数据的.有些加载更多的实现是一到最后一个数据,就开始加载更多.但在第一页数据不满一屏的情况下,触发了加载很多,很违背直觉. BaseRecyclerViewAdapterHelper 就采用了这种实现,大家可以去看源码. 而且一般第一页的请求,我们一般会有自己的一个 loading 视图,这样不满一屏的情况下,还有一个加载更多的视图,这是不太合理的.


      以上 demo 仅供参考,大家可以进一步自己封装和实现.可以自己实现个 MultiTypeAdapter 并把代码整合到里面去,这样用起来可能会更方便点.


      效果图


      结合 MultiType 实现加载更多 
      loadmore.gif 
posted @ 2018-10-19 08:21  天涯海角路  阅读(325)  评论(0)    收藏  举报