Android 列表页面终极封装:SmartRefreshLayout + BRVAH 实现下拉刷新和加载更多
在 Android 开发中,列表页面是常见的 UI 设计模式,而下拉刷新和加载更多是提升用户体验的关键功能。本文将带你从零开始,封装一个高复用性的 SmartRefreshHelper
工具类,结合 SmartRefreshLayout
和 BRVAH
,实现高效、灵活的列表页面。你将学到:
- 如何封装
SmartRefreshHelper
工具类,简化列表页面的实现。 - 支持下拉刷新、加载更多、空布局和加载更多失败处理。
- 通过代码示例和布局文件,快速上手并应用到实际项目中。
包括 SmartRefreshLayout
和 BRVAH
的封装、下拉刷新和加载更多功能、空布局支持、加载更多失败处理 以及 网络请求封装。所有内容都经过优化,确保代码简洁、高效且易于扩展。
1. 添加依赖
在 build.gradle
中添加以下依赖:
dependencies {
// SmartRefreshLayout 下拉刷新和加载更多
implementation 'io.github.scwang90:refresh-layout-kernel:2.0.6' // 核心库
implementation 'io.github.scwang90:refresh-header-classics:2.0.6' // 经典刷新头
implementation 'io.github.scwang90:refresh-footer-classics:2.0.6' // 经典加载更多
// BRVAH 高效适配器
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.14'
}
2. 布局文件
activity_main.xml
<?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">
<!-- RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Item"
android:textSize="18sp"/>
</LinearLayout>
empty_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No data available"
android:textSize="18sp"/>
</LinearLayout>
3. 封装 SmartRefreshHelper 工具类
import android.app.Activity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.scwang.smart.refresh.layout.api.RefreshLayout;
import com.scwang.smart.refresh.layout.listener.OnLoadMoreListener;
import com.scwang.smart.refresh.layout.listener.OnRefreshListener;
import java.util.List;
/**
* 封装 SmartRefreshLayout 和 BRVAH 的工具类
* 功能:支持下拉刷新、加载更多、空布局和加载更多失败处理
*/
public class SmartRefreshHelper<T> {
private final Activity activity;
private final RefreshLayout refreshLayout;
private final RecyclerView recyclerView;
private final BaseQuickAdapter<T, ?> adapter;
private final DataLoader<T> dataLoader;
private int page = 1; // 当前页码
/**
* 构造函数
*
* @param activity Activity 实例
* @param refreshLayoutId SmartRefreshLayout 的 ID
* @param recyclerViewId RecyclerView 的 ID
* @param adapter 数据适配器
* @param dataLoader 数据加载器
*/
public SmartRefreshHelper(Activity activity, int refreshLayoutId, int recyclerViewId,
BaseQuickAdapter<T, ?> adapter, DataLoader<T> dataLoader) {
this.activity = activity;
this.refreshLayout = activity.findViewById(refreshLayoutId);
this.recyclerView = activity.findViewById(recyclerViewId);
this.adapter = adapter;
this.dataLoader = dataLoader;
// 初始化 RecyclerView
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
recyclerView.setAdapter(adapter);
// 设置下拉刷新和加载更多监听器
initRefreshListener();
}
/**
* 初始化下拉刷新和加载更多监听器
*/
private void initRefreshListener() {
// 下拉刷新
refreshLayout.setOnRefreshListener((RefreshLayout refreshLayout) -> {
page = 1; // 重置页码
loadData(page, true); // 加载第一页数据
});
// 加载更多
refreshLayout.setOnLoadMoreListener((RefreshLayout refreshLayout) -> {
page++; // 加载下一页
loadData(page, false);
});
}
/**
* 加载数据
*
* @param page 当前页码
* @param isRefresh 是否是刷新操作
*/
private void loadData(int page, boolean isRefresh) {
dataLoader.loadData(page, new DataLoader.Callback<T>() {
@Override
public void onSuccess(List<T> data) {
if (isRefresh) {
adapter.setList(data); // 刷新数据
refreshLayout.finishRefresh(); // 结束刷新
} else {
adapter.addData(data); // 添加更多数据
refreshLayout.finishLoadMore(); // 结束加载更多
}
}
@Override
public void onFailure(String message) {
if (isRefresh) {
refreshLayout.finishRefresh(false); // 刷新失败
} else {
refreshLayout.finishLoadMore(false); // 加载更多失败
}
}
});
}
/**
* 设置空布局
*
* @param emptyLayoutId 空布局的资源 ID
*/
public void setEmptyView(int emptyLayoutId) {
adapter.setEmptyView(emptyLayoutId);
}
/**
* 数据加载器接口
*/
public interface DataLoader<T> {
void loadData(int page, Callback<T> callback);
interface Callback<T> {
void onSuccess(List<T> data);
void onFailure(String message);
}
}
}
4. 适配器实现
MyAdapter
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import java.util.List;
public class MyAdapter extends BaseQuickAdapter<String, BaseViewHolder> {
public MyAdapter(List<String> data) {
super(R.layout.item_layout, data);
}
@Override
protected void convert(@NonNull BaseViewHolder holder, String item) {
// 绑定数据到视图
holder.setText(R.id.textView, item);
}
}
5. 在 Activity 中使用
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private SmartRefreshHelper<String> smartRefreshHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化适配器
MyAdapter adapter = new MyAdapter(new ArrayList<>());
// 初始化 SmartRefreshHelper
smartRefreshHelper = new SmartRefreshHelper<>(
this,
R.id.refreshLayout,
R.id.recyclerView,
adapter,
new SmartRefreshHelper.DataLoader<String>() {
@Override
public void loadData(int page, SmartRefreshHelper.DataLoader.Callback<String> callback) {
// 模拟网络请求
new Handler().postDelayed(() -> {
List<String> data = getData(page); // 获取数据
if (data.isEmpty()) {
callback.onFailure("No more data"); // 加载失败
} else {
callback.onSuccess(data); // 加载成功
}
}, 2000); // 2秒延迟
}
}
);
// 设置空布局
smartRefreshHelper.setEmptyView(R.layout.empty_layout);
// 首次加载数据
smartRefreshHelper.loadData(1, true);
}
/**
* 模拟获取数据
*
* @param page 当前页码
* @return 数据列表
*/
private List<String> getData(int page) {
List<String> data = new ArrayList<>();
for (int i = 0; i < 10; i++) {
data.add("Item " + (page * 10 + i));
}
return data;
}
}
6. 优势
- 空布局支持:当数据为空时显示提示。
- 加载更多失败处理:提升用户体验。
- 网络请求封装:通过
DataLoader
接口解耦网络请求逻辑。 - 代码复用性优化:通过泛型支持多种数据类型。
- 简洁高效:逻辑清晰,易于维护和扩展。
7. 总结
通过优化后的 SmartRefreshHelper
,我们实现了一个功能强大且灵活的列表页面,支持下拉刷新、加载更多、空布局和加载更多失败处理。这种封装方式不仅提高了代码的复用性,还简化了开发流程。
核心功能
- 下拉刷新:重置数据并加载第一页。
- 加载更多:追加数据并加载下一页。
- 空布局:当数据为空时显示提示。
- 加载更多失败处理:提升用户体验。
扩展功能
- 自定义刷新头和加载更多:满足个性化需求。
- 支持多种数据类型:通过泛型实现。