下拉刷新、上拉加载在安卓里面简直就是无处不在,可是不知道为什么谷歌不直接提供一个这样的控件,网上相关的文章应该多的数不清了,我这只是简单给自己总结一个。
最佳办法
要说最佳办法肯定是用别人稳定的开源库了,我这就直接推荐鼎鼎大名的 SmartRefreshLayout 了
https://github.com/scwang90/SmartRefreshLayout
简单讲下用法吧,看下面:
implementation 'com.scwang.smart:refresh-layout-kernel:2.0.3'
这里有部分限制,具体可以看 github 文档,我这是 androidx 简单使用就加这一个。
<?xml version="1.0" encoding="utf-8"?>
<com.scwang.smart.refresh.layout.SmartRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.scwang.smart.refresh.header.ClassicsHeader
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:background="#fff" />
<com.scwang.smart.refresh.footer.ClassicsFooter
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
RefreshLayout refreshLayout = (RefreshLayout)findViewById(R.id.refreshLayout);
refreshLayout.setRefreshHeader(new ClassicsHeader(this));
refreshLayout.setRefreshFooter(new ClassicsFooter(this));
refreshLayout.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh(RefreshLayout refreshlayout) {
refreshlayout.finishRefresh(2000/*,false*/);//传入false表示刷新失败
}
});
refreshLayout.setOnLoadMoreListener(new onl oadMoreListener() {
@Override
public void onl oadMore(RefreshLayout refreshlayout) {
refreshlayout.finishLoadMore(2000/*,false*/);//传入false表示加载失败
}
});
差劲办法
差劲的办法就是自己搞一套(当然写得好另说,写不好就是差劲),虽然不是很难,也好理解,但是交接给别人,真的可以把头搞大,这也是我写这篇文章的原因之一,就不多说了。
简单用法
有时候不想引入太多的库,又不想自己搞一套,就可以参考下面我这种方法了。
这里也用到了一个大名鼎鼎的开源库 BaseRecyclerViewAdapterHelper,具体使用方法可以谷歌搜索一下。我的思路是使用谷歌官方的 SwipeRefreshLayout 配合 BaseRecyclerViewAdapterHelper 共同实现上拉刷新和下拉加载的,也是 BaseRecyclerViewAdapterHelper 所推荐的方法。其中 SwipeRefreshLayout 用以实现下拉刷新,而 BaseRecyclerViewAdapterHelper 用来实现上拉加载,代码肯定比用别人开源库复杂点,但是还是挺简单的,下面看用法:
- XML 布局文件
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/list_trajectory"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="@null"
android:divider="@null"
android:dividerHeight="@dimen/edge_distance_small"/>
</android.support.v4.widget.SwipeRefreshLayout>
- Java 代码
RecyclerView recyclerView;
SwipeRefreshLayout refreshLayout;
private ItemAdapter adapter; //列表适配器
private boolean isReload = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
//设置下拉控件
initRefreshLayout();
//设置列表及适配器
initRecyclerView();
}
private void initRefreshLayout() {
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
isReload = true;
refreshLayout.setRefreshing(true);
adapter.setEnableLoadMore(false);
//加载数据
...
}
});
}
private void initRecyclerView() {
//设置recyclerView
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//设置列表适配器
adapter = new ItemAdapter(R.layout.item, mData);
//设置空布局
adapter.setEmptyView(R.layout.item_empty, (ViewGroup) recyclerView.getParent());
//启用上拉刷新
adapter.setEnableLoadMore(true);
adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
@Override
public void onl oadMoreRequested() {
refreshLayout.setEnabled(false);
//获取数据
...
}
},recyclerView);
recyclerView.setAdapter(adapter);
}
//获取数据成功
public void onSuccess(String msg, List<Item> data) {
//继续加载
if (isReload) {
mData.clear();
isReload = false;
}
mData.addAll(data);
adapter.loadMoreComplete();
adapter.notifyDataSetChanged();
adapter.setEnableLoadMore(true);
refreshLayout.setRefreshing(false);
//这里设置了一页20条数据
if (data.size() < 20) {
adapter.loadMoreEnd();
}
}
//获取数据失败
public void onFailed(String msg, int errCode) {
adapter.loadMoreComplete();
adapter.setEnableLoadMore(true);
refreshLayout.setRefreshing(false);
}
写的不是很清楚,主要有下面几点要理解
-
下拉刷新和上拉加载状态交替问题
这两个状态不能同时出现,需要在请求数据和结束请求数据的时候,改变 refreshLayout 和 adapter 的状态,具体看下面代码:
refreshLayout.setRefreshing(true); adapter.setEnableLoadMore(false);
-
加载数据完成和加载数据结束
在 BaseRecyclerViewAdapterHelper 中提供了两种方法,一个是 loadMoreComplete,表示单次的数据请求加载完成,底部 footer 不再显示,另一个是 loadMoreEnd,表示数据全部加载完成,不会再触发上拉加载了,这个尤其注意无论成功或者失败,都应该调用 loadMoreComplete 方法,而全部数据加载了要调用 loadMoreEnd 方法。
结语
这里讲了三种实现下拉刷新、上拉加载的方法,看需要使用吧。
end