|
|
|
|
@ -1,177 +1,204 @@
|
|
|
|
|
// 定义包名
|
|
|
|
|
package com.monke.monkeybook.widget.refreshview;
|
|
|
|
|
|
|
|
|
|
import android.os.Handler;
|
|
|
|
|
import android.os.Looper;
|
|
|
|
|
import android.support.v7.widget.RecyclerView;
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
|
import android.view.View;
|
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
|
import android.widget.FrameLayout;
|
|
|
|
|
import android.widget.TextView;
|
|
|
|
|
import android.os.Handler; // 导入 Handler 类,用于处理线程间通信和执行任务
|
|
|
|
|
import android.os.Looper; // 导入 Looper 类,用于控制线程的消息循环
|
|
|
|
|
import android.support.v7.widget.RecyclerView; // 导入 RecyclerView 类,支持高效的列表展示
|
|
|
|
|
import android.util.Log; // 导入 Log 类,用于调试日志
|
|
|
|
|
import android.view.LayoutInflater; // 导入 LayoutInflater 类,用于将布局文件转换为 View 对象
|
|
|
|
|
import android.view.View; // 导入 View 类,所有 UI 控件的基类
|
|
|
|
|
import android.view.ViewGroup; // 导入 ViewGroup 类,视图的容器类
|
|
|
|
|
import android.widget.FrameLayout; // 导入 FrameLayout 类,允许堆叠子视图的布局
|
|
|
|
|
import android.widget.TextView; // 导入 TextView 类,用于显示文本
|
|
|
|
|
|
|
|
|
|
import com.monke.monkeybook.R;
|
|
|
|
|
import com.monke.monkeybook.R; // 导入应用资源类,访问资源文件
|
|
|
|
|
|
|
|
|
|
// 创建抽象类 RefreshRecyclerViewAdapter,继承自 RecyclerView.Adapter
|
|
|
|
|
public abstract class RefreshRecyclerViewAdapter extends RecyclerView.Adapter {
|
|
|
|
|
private final int LOADMORETYPE = 2001;
|
|
|
|
|
private final int LOADMORETYPE = 2001; // 加载更多的视图类型
|
|
|
|
|
|
|
|
|
|
private Handler handler;
|
|
|
|
|
private int isRequesting = 0; //0是未执行网络请求 1是正在下拉刷新 2是正在加载更多
|
|
|
|
|
private Boolean needLoadMore = false;
|
|
|
|
|
private Boolean isAll = false; //判断是否还有更多
|
|
|
|
|
private Boolean loadMoreError = false;
|
|
|
|
|
private Handler handler; // 处理线程间通信的 Handler
|
|
|
|
|
private int isRequesting = 0; // 当前请求状态: 0-未请求,1-正在下拉刷新,2-正在加载更多
|
|
|
|
|
private Boolean needLoadMore = false; // 是否需要加载更多
|
|
|
|
|
private Boolean isAll = false; // 判断是否还有更多数据
|
|
|
|
|
private Boolean loadMoreError = false; // 判断是否加载更多时发生错误
|
|
|
|
|
|
|
|
|
|
private OnClickTryAgainListener clickTryAgainListener;
|
|
|
|
|
private OnClickTryAgainListener clickTryAgainListener; // 加载失败重试监听器接口
|
|
|
|
|
|
|
|
|
|
// 点击重试的监听器接口
|
|
|
|
|
public interface OnClickTryAgainListener {
|
|
|
|
|
public void loadMoreErrorTryAgain();
|
|
|
|
|
public void loadMoreErrorTryAgain();// 加载失败时的重试方法
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构造函数
|
|
|
|
|
public RefreshRecyclerViewAdapter(Boolean needLoadMore) {
|
|
|
|
|
this.needLoadMore = needLoadMore;
|
|
|
|
|
handler = new Handler();
|
|
|
|
|
this.needLoadMore = needLoadMore; // 设置是否需要加载更多
|
|
|
|
|
handler = new Handler(); // 初始化 Handler
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取请求状态
|
|
|
|
|
public int getIsRequesting() {
|
|
|
|
|
return isRequesting;
|
|
|
|
|
return isRequesting; // 返回当前请求状态
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置请求状态
|
|
|
|
|
public void setIsRequesting(int isRequesting, Boolean needNoti) {
|
|
|
|
|
this.isRequesting = isRequesting;
|
|
|
|
|
if (this.isRequesting == 1) {
|
|
|
|
|
isAll = false;
|
|
|
|
|
this.isRequesting = isRequesting; // 更新请求状态
|
|
|
|
|
if (this.isRequesting == 1) { // 如果正在请求刷新
|
|
|
|
|
isAll = false; // 设置为没有更多数据
|
|
|
|
|
}
|
|
|
|
|
// 根据需要通知数据变化
|
|
|
|
|
if (needNoti) {
|
|
|
|
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
|
|
|
|
notifyItemRangeChanged(getItemCount(), getItemCount() - getItemcount());
|
|
|
|
|
notifyItemRangeChanged(getItemCount(), getItemCount() - getItemcount()); // 通知数据范围变化
|
|
|
|
|
} else {
|
|
|
|
|
handler.post(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
notifyDataSetChanged();
|
|
|
|
|
notifyDataSetChanged(); // 在主线程中通知数据已更新
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建视图持有者
|
|
|
|
|
@Override
|
|
|
|
|
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
|
|
|
|
if (viewType == LOADMORETYPE) {
|
|
|
|
|
if (viewType == LOADMORETYPE) { // 如果是加载更多类型
|
|
|
|
|
return new LoadMoreViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.view_refresh_loadmore, parent, false));
|
|
|
|
|
} else
|
|
|
|
|
return onCreateViewholder(parent, viewType);
|
|
|
|
|
} else {
|
|
|
|
|
return onCreateViewholder(parent, viewType); // 否则调用抽象方法创建其他类型的视图持有者
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 抽象方法,创建其他类型的视图持有者
|
|
|
|
|
public abstract RecyclerView.ViewHolder onCreateViewholder(ViewGroup parent, int viewType);
|
|
|
|
|
|
|
|
|
|
// 绑定视图数据
|
|
|
|
|
@Override
|
|
|
|
|
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
|
|
|
|
|
if (holder.getItemViewType() == LOADMORETYPE) {
|
|
|
|
|
if (holder.getItemViewType() == LOADMORETYPE) { // 如果是加载更多视图
|
|
|
|
|
if (!loadMoreError) {
|
|
|
|
|
((LoadMoreViewHolder) holder).tvLoadMore.setText("正在加载...");
|
|
|
|
|
((LoadMoreViewHolder) holder).tvLoadMore.setText("正在加载..."); // 显示加载中
|
|
|
|
|
} else {
|
|
|
|
|
((LoadMoreViewHolder) holder).tvLoadMore.setText("加载失败,点击重试");
|
|
|
|
|
((LoadMoreViewHolder) holder).tvLoadMore.setText("加载失败,点击重试"); // 显示加载失败信息
|
|
|
|
|
}
|
|
|
|
|
// 设置点击事件
|
|
|
|
|
((LoadMoreViewHolder) holder).tvLoadMore.setOnClickListener(new View.OnClickListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onClick(View v) {
|
|
|
|
|
if (null != clickTryAgainListener && loadMoreError) {
|
|
|
|
|
clickTryAgainListener.loadMoreErrorTryAgain();
|
|
|
|
|
loadMoreError = false;
|
|
|
|
|
((LoadMoreViewHolder) holder).tvLoadMore.setText("正在加载...");
|
|
|
|
|
clickTryAgainListener.loadMoreErrorTryAgain(); // 调用重试方法
|
|
|
|
|
loadMoreError = false; // 重置加载错误状态
|
|
|
|
|
((LoadMoreViewHolder) holder).tvLoadMore.setText("正在加载..."); // 更新加载状态
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else
|
|
|
|
|
onBindViewholder(holder, position);
|
|
|
|
|
} else {
|
|
|
|
|
onBindViewholder(holder, position); // 绑定其他类型视图的数据
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 抽象方法,绑定其他类型视图的数据
|
|
|
|
|
public abstract void onBindViewholder(RecyclerView.ViewHolder holder, int position);
|
|
|
|
|
|
|
|
|
|
// 获取视图类型
|
|
|
|
|
@Override
|
|
|
|
|
public int getItemViewType(int position) {
|
|
|
|
|
if (needLoadMore && isRequesting != 1 && !isAll && position == getItemCount() - 1 && getItemcount() > 0) {
|
|
|
|
|
return LOADMORETYPE;
|
|
|
|
|
return LOADMORETYPE; // 如果满足条件,返回加载更多视图类型
|
|
|
|
|
} else {
|
|
|
|
|
return getItemViewtype(position);
|
|
|
|
|
return getItemViewtype(position); // 否则返回其他视图类型
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 抽象方法,获取其他类型视图的类型
|
|
|
|
|
public abstract int getItemViewtype(int position);
|
|
|
|
|
|
|
|
|
|
// 获取项计数
|
|
|
|
|
@Override
|
|
|
|
|
public int getItemCount() {
|
|
|
|
|
if (needLoadMore && isRequesting != 1 && !isAll && getItemcount() > 0) {
|
|
|
|
|
return getItemcount() + 1;
|
|
|
|
|
} else
|
|
|
|
|
return getItemcount();
|
|
|
|
|
return getItemcount() + 1; // 如果需要加载更多,返回总数 + 1(加载更多视图)
|
|
|
|
|
} else {
|
|
|
|
|
return getItemcount(); // 返回正常的项计数
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public abstract int getItemcount();
|
|
|
|
|
public abstract int getItemcount(); // 抽象方法,获取正常的项计数
|
|
|
|
|
|
|
|
|
|
// 设置是否有更多数据
|
|
|
|
|
public void setIsAll(Boolean isAll, Boolean needNoti) {
|
|
|
|
|
this.isAll = isAll;
|
|
|
|
|
this.isAll = isAll; // 更新是否有更多数据
|
|
|
|
|
// 根据需要通知数据变化
|
|
|
|
|
if (needNoti) {
|
|
|
|
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
|
|
|
|
// notifyItemRangeChanged(getItemCount(),getItemCount()-getItemcount());
|
|
|
|
|
if (getItemCount() > getItemcount()) {
|
|
|
|
|
notifyItemRangeChanged(getItemCount(), getItemCount() - getItemcount());
|
|
|
|
|
} else
|
|
|
|
|
notifyItemRemoved(getItemCount() + 1);
|
|
|
|
|
notifyItemRangeChanged(getItemCount(), getItemCount() - getItemcount()); // 通知数据范围变化
|
|
|
|
|
} else {
|
|
|
|
|
notifyItemRemoved(getItemCount() + 1); // 通知加载更多视图移除
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
handler.post(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
notifyDataSetChanged();
|
|
|
|
|
notifyDataSetChanged(); // 在主线程中通知数据已更新
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 加载更多视图持有者类
|
|
|
|
|
class LoadMoreViewHolder extends RecyclerView.ViewHolder {
|
|
|
|
|
FrameLayout llLoadMore;
|
|
|
|
|
TextView tvLoadMore;
|
|
|
|
|
FrameLayout llLoadMore; // 加载更多的容器
|
|
|
|
|
TextView tvLoadMore; // 加载更多的文本视图
|
|
|
|
|
|
|
|
|
|
// 构造函数
|
|
|
|
|
public LoadMoreViewHolder(View itemView) {
|
|
|
|
|
super(itemView);
|
|
|
|
|
llLoadMore = (FrameLayout) itemView.findViewById(R.id.ll_loadmore);
|
|
|
|
|
tvLoadMore = (TextView) itemView.findViewById(R.id.tv_loadmore);
|
|
|
|
|
llLoadMore = (FrameLayout) itemView.findViewById(R.id.ll_loadmore); // 获取加载更多的容器
|
|
|
|
|
tvLoadMore = (TextView) itemView.findViewById(R.id.tv_loadmore); // 获取加载更多文本视图
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 判断是否可以加载更多
|
|
|
|
|
public Boolean canLoadMore() {
|
|
|
|
|
return needLoadMore && isRequesting == 0 && !isAll && getItemcount() > 0;
|
|
|
|
|
return needLoadMore && isRequesting == 0 && !isAll && getItemcount() > 0; // 返回是否满足加载更多条件
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取重试监听器
|
|
|
|
|
public OnClickTryAgainListener getClickTryAgainListener() {
|
|
|
|
|
return clickTryAgainListener;
|
|
|
|
|
return clickTryAgainListener; // 返回重试监听器
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置重试监听器
|
|
|
|
|
public void setClickTryAgainListener(OnClickTryAgainListener clickTryAgainListener) {
|
|
|
|
|
this.clickTryAgainListener = clickTryAgainListener;
|
|
|
|
|
|
|
|
|
|
this.clickTryAgainListener = clickTryAgainListener; // 赋值给重试监听器
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取加载更多错误状态
|
|
|
|
|
public Boolean getLoadMoreError() {
|
|
|
|
|
return loadMoreError;
|
|
|
|
|
return loadMoreError; // 返回加载更多错误状态
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置加载更多错误
|
|
|
|
|
public void setLoadMoreError(Boolean loadMoreError, Boolean needNoti) {
|
|
|
|
|
this.isRequesting = 0;
|
|
|
|
|
this.loadMoreError = loadMoreError;
|
|
|
|
|
this.isRequesting = 0; // 重置请求状态
|
|
|
|
|
this.loadMoreError = loadMoreError; // 设置加载错误状态
|
|
|
|
|
// 根据需要通知数据变化
|
|
|
|
|
if (needNoti) {
|
|
|
|
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
|
|
|
|
notifyDataSetChanged();
|
|
|
|
|
notifyDataSetChanged(); // 在主线程中通知数据已更新
|
|
|
|
|
} else {
|
|
|
|
|
handler.post(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
notifyDataSetChanged();
|
|
|
|
|
notifyDataSetChanged(); // 在主线程中通知数据已更新
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|