当前位置 博文首页 > 高远的博客:易生活(五)-APP--上拉加载更多工具类封装思路及实现

    高远的博客:易生活(五)-APP--上拉加载更多工具类封装思路及实现

    作者:[db:作者] 时间:2021-09-06 22:45

    背景

    1. 在项目开发过程中遇到这样一个问题:我们团队有用到RecyclerView,由于这是新特性,许多刷新框架还不支持,于是就选择了google官方的刷新框架SwipeRefreshLayout,但是这个框架只有下拉刷新,没有上拉加载更多。
    2. 在《ListView刷新原理及实现》已经说过自己动手写刷新以及加载原理,于是项目中打算自己写上拉加载更多,刷新用SwipeRefreshLayout。
    3. 问题是,自己写上拉加载更多会用到大量的代码去实现这个逻辑,非常繁琐。
    4. 现尝试对这一块进行封装。[已解决]

    思路、实现及问题

    思路

    • 将判断手指滑动到控件底部以及滑动到底部这一块逻辑抽离到父类,在子类中直接实现这个父类即可。这一块有大量代码,如果能实现就可以大量节俭代码量,提高工作效率。
    • 同时,需要通过一定的手段通知子类什么时候滑动到底部,以便子类去执行“加载更多”操作。这里我们通过回调实现。
    • 难点在于,在安卓activity和fragment中不能像我们平时写代码可以“实例化”(new xxx(传递子类对象通知父类))。我们通过super.init(子类对象)去通知父类。
    • 那么,问题又来了,现在这是一个“工具类”,如果使用super.init(子类对象),如何实现共用?太过局限,不能实现共用。
    • 我们通过“接口”的形式解决这个问题。让子类全部实现一个接口,在父类中实例化接口即可!

    实现

    • 工具类

      import android.os.Handler;
      import android.os.Message;
      import android.support.v7.app.AppCompatActivity;
      import android.widget.AbsListView;
      
      /**
       * Created by wgyscsf on 2016/6/1.
       * 邮箱:wgyscsf@163.com
       * 博客:http://blog.csdn.net/wgyscsf
       */
      
      
      /**
       * 作用:该工具类简化了滑到底部的逻辑判断以及何时触发上拉加在更多;可以直接写上拉加载更多操作。(简单来说,你不用再去写何时到listview的底部这一块的操作以及发送加载更多的handler请求)
       * 使用方式(三步):
       * 1、让你的activity继承这个LoadMoreActivity(不再继承原有AppCompatActivity)
       * 2、在你的onCreate方法中写 super.initLoadMore(this);
       * 3、让你的activity实现LoadMoreActivity.LoadMoreActivityListener接口,在实现的方法中即可以写上拉加载更多的操作(自己维护页码变化)。
       * 注意:原有操作不便,例如添加footer、添加ScrollListener监听( listview.setOnScrollListener(this);)。
       */
      
      public class LoadMoreActivity extends AppCompatActivity implements  AbsListView.OnScrollListener{
          private LoadMoreActivityListener mLoadMoreActivityListener;
          //这个方法靠子类调用,完成自身的初始化(这个“自身”指的是实现LoadMoreActivityListener接口的activity)。
          public void initLoadMore(LoadMoreActivityListener loadMoreActivityListener){
              this.mLoadMoreActivityListener=loadMoreActivityListener;
          }
          public static final int LOAD_LOGIC = 1;//上拉逻辑
          private  int result1;//上拉加载更多相关
          private  int result2;//上拉加载更多相关
          //上拉加载更多操作
          Handler mHandler = new Handler() {
              @Override
              public void handleMessage(Message msg) {
                  switch (msg.what) {
                      case LOAD_LOGIC:
                          mLoadMoreActivityListener.loadMore();//核心代码:这里通知子类可以加载更多了。
                          break;
                  }
      
              }
          };
          //监听状态改变
          @Override
          public void onScrollStateChanged(AbsListView view, int scrollState) {
              switch (scrollState) {
                  case SCROLL_STATE_IDLE:
                      //滑动结束
                      if (result1 >= result2) {
                          //只发送一次,防止多次加载数据
                          if (!mHandler.hasMessages(LOAD_LOGIC))
                              mHandler.sendEmptyMessage(LOAD_LOGIC);
                      }
                      break;
                  case SCROLL_STATE_FLING:
      
                      break;
                  case SCROLL_STATE_TOUCH_SCROLL:
                      //滑动中
                      break;
              }
          }
      
          //滑动结束之后执行
          @Override
          public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
              result1 = firstVisibleItem + visibleItemCount;
              result2 = totalItemCount;
          }
      
      //接口,这个接口要靠继承上述LoadMoreActivity去实现,在loadMore()中实现加载更多操作
          public interface LoadMoreActivityListener{
              //这里写加载更多的逻辑,这个方法要靠实现类去实现,去完成加载更多操作。
              public void loadMore();
          }
      }
      
    • 使用

      1. 让你的activity extends LoadMoreActivity implements LoadMoreActivity.LoadMoreActivityListener
      2. onCreate(Bundle savedInstanceState)中写super.onCreate(savedInstanceState);
      3. 在实现的方法loadMore()中写加载更多操作即可。

    问题

    • 问题也是很明显的,这个工具类只能应用于activity之中,对于在fragment是不能使用的。
    • 我也尝试解决着去解决,但是fragment和activity根本没有直接的父类关系。
    • 所以很难封装到一起,共用一个工具类。
    • 另一方面,由于RecyclerView的新特性,这个工具类也不能应用于RecyclerView。

    总结

    • 虽然这个工具类有很大的局限性,但是仍然比较实用。至少对于一般的需要实现上拉加载更多是可以实现基本的功能的,并且大量减少代码量。
    • 我们可以看出,在上述这个工具类的抽取过程中,运用到了继承、接口(重点)、回调去实现这个工具类。
    • 灵活运用继承关系、面向接口编程、回调思想可以很大程度上优化我们的代码以及实现对代码的封装。

    附,fragment上拉加载更多工具类(实现和上述工具类一致,只是继承的父类变了)

        import android.os.Handler;
        import android.os.Message;
        import android.support.v4.app.Fragment;
        import android.widget.AbsListView;
    
        /**
         * Created by wgyscsf on 2016/6/1.
         * 邮箱:wgyscsf@163.com
         * 博客:http://blog.csdn.net/wgyscsf
         */
    
    
        /**
         * 作用:该工具类简化了滑到底部的逻辑判断以及何时触发上拉加在更多;可以直接写上拉加载更多操作。(简单来说,你不用再去写何时到listview的底部这一块的操作以及发送加载更多的handler请求)
         * 使用方式(三步):
         * 1、让你的Fragment继承这个LoadMoreFragment(不再继承原有Fragment)
         * 2、在你的onCreateView方法中写 super.initLoadMore(this);
         * 3、让你的Fragment实现 LoadMoreFragment.LoadMoreFragmentListener 接口,在实现的方法中即可以写上拉加载更多的操作(自己维护页码变化)。
         * 注意:原有操作不便,例如添加footer、添加ScrollListener监听( listview.setOnScrollListener(this);)。
         */
    
    
    
        public class LoadMoreFragment extends Fragment implements  AbsListView.OnScrollListener{
            private LoadMoreFragmentListener mLoadMoreFragmentListener;
            public void initLoadMore(LoadMoreFragmentListener loadMoreFragmentListener){
                this.mLoadMoreFragmentListener=loadMoreFragmentListener;
            }
            public static final int LOAD_LOGIC = 1;//上拉逻辑
            private  int result1;//上拉加载更多相关
            private  int result2;//上拉加载更多相关
            //这里进行刷新、上拉加载更多逻辑、上拉加载更多操作
            Handler mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case LOAD_LOGIC:
                            mLoadMoreFragmentListener.loadMore();
                            break;
                    }
    
                }
            };
    
            //监听状态改变
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                switch (scrollState) {
                    case SCROLL_STATE_IDLE:
                        //滑动结束
                        if (result1 >= result2) {
                            //只发送一次,防止多次加载数据
                            if (!mHandler.hasMessages(LOAD_LOGIC))
                                mHandler.sendEmptyMessage(LOAD_LOGIC);
                        }
                        break;
                    case SCROLL_STATE_FLING:
    
                        break;
                    case SCROLL_STATE_TOUCH_SCROLL:
                        //滑动中
                        break;
                }
            }
    
            //滑动结束之后执行
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                result1 = firstVisibleItem + visibleItemCount;
                result2 = totalItemCount;
            }
    
    
            public interface LoadMoreFragmentListener{
                //这里写加载更多的逻辑
                public void loadMore();
            }
        }
    
    cs