版权声明:本文为博主高远原创文章,转载请注明出处:http://blog.csdn.net/wgyscsf https://blog.csdn.net/wgyscsf/article/details/51578456
背景
- 在项目开发过程中遇到这样一个问题:我们团队有用到RecyclerView,由于这是新特性,许多刷新框架还不支持,于是就选择了google官方的刷新框架SwipeRefreshLayout,但是这个框架只有下拉刷新,没有上拉加载更多。
- 在《ListView刷新原理及实现》已经说过自己动手写刷新以及加载原理,于是项目中打算自己写上拉加载更多,刷新用SwipeRefreshLayout。
- 问题是,自己写上拉加载更多会用到大量的代码去实现这个逻辑,非常繁琐。
- 现尝试对这一块进行封装。[已解决]
思路、实现及问题
思路
- 将判断手指滑动到控件底部以及滑动到底部这一块逻辑抽离到父类,在子类中直接实现这个父类即可。这一块有大量代码,如果能实现就可以大量节俭代码量,提高工作效率。
- 同时,需要通过一定的手段通知子类什么时候滑动到底部,以便子类去执行“加载更多”操作。这里我们通过回调实现。
- 难点在于,在安卓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. * 邮箱:[email protected] * 博客: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(); } }
使用
- 让你的activity
extends LoadMoreActivity implements LoadMoreActivity.LoadMoreActivityListener
- 在
onCreate(Bundle savedInstanceState)
中写super.onCreate(savedInstanceState);
- 在实现的方法
loadMore()
中写加载更多操作即可。
- 让你的activity
问题
- 问题也是很明显的,这个工具类只能应用于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.
* 邮箱:[email protected]
* 博客: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();
}
}