import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.yds.tingli.R;
public class AppMainCardView extends RelativeLayout {
TextView nameView;
public AppMainCardView(Context context) {
this(context,null);
}
public AppMainCardView(Context context, AttributeSet attrs) {
super(context, attrs);
View view = LayoutInflater.from(context).inflate(R.layout.mainitem, this, true);
nameView = view.findViewById(R.id.title);
}
public void setName(String name) {
nameView.setText(name);
}
}
public class Constance {
public static final int ITEM_IN_A_PAGE = 20;
}
import com.yds.tingli.ElyBean;
import java.util.ArrayList;
import java.util.List;
public class PartBean {
public String title;//2020年12月英语四级听力真题 短文(1)
public List<ElyBean> elyBeanList = new ArrayList<>();
public String getName(){
return title;
}
}
import android.content.Context;
import android.util.Log;
import android.view.View;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class PullUpRecyclerController {
private RecyclerView mRecyclerView;
private RecyclerAdapter mAdapter;
private int mLastVisibleItemPosition = 0;
private LinearLayoutManager mLayoutManager;
private Context mContext;
private OnNeedLoadListener mOnNeedLoadListener;
public PullUpRecyclerController(Context context, RecyclerView recyclerView) {
onCreate(context, recyclerView);
}
protected void onCreate(Context context, RecyclerView recyclerView) {
mContext = context;
mRecyclerView = recyclerView;
mLayoutManager = new LinearLayoutManager(context);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
}
public View getRecyclerView() {
return mRecyclerView;
}
/**
* 构造方法已经调用此方法 当想要更换listener时再调用此方法
*
* @param listener
*/
public void setOnNeedLoadListener(OnNeedLoadListener listener) {
this.mOnNeedLoadListener = listener;
}
public interface OnNeedLoadListener {
public void loadMore(int from, int length);
}
/**
* 第一次显示recyclerView的时候调用的方法。
*
* @param list
*/
@SuppressWarnings("deprecation")
public void showFirstpageItems(List<PartBean> list) {
mAdapter = new RecyclerAdapter(mContext, list);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView,
int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE
// && mLastVisibleItemPosition + 1 >= mAdapter
&& mLastVisibleItemPosition + 1 == mAdapter
.getItemCount()) {
if (mOnNeedLoadListener != null) {
/**
* 在调用回调接口前,要先确定是否已经在回调了 没有在回调的话,还要更新footer
*/
if (RecyclerModule.isLoadingMore) {
Log.e("aaaaa", "RecyclerModule.isLoadingMore");
return;
}
RecyclerModule.isLoadingMore = true;
setLoadStatusNrefreshFooter(RecyclerAdapter.LoadStatus.LOADING_MORE);
/**
* 调用回调接口
*/
mOnNeedLoadListener.loadMore(mAdapter.getItemCount() - 1,
Constance.ITEM_IN_A_PAGE);
}
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
mLastVisibleItemPosition = mLayoutManager
.findLastVisibleItemPosition();
}
});
}
/**
* 显示更多条目 应该先调用showFirstpageItems方法
*
* @param list
*/
public void showMoreItems(List<PartBean> list) {
mAdapter.addAllNRefresh(list);
}
/**
* 调用adapter的同名方法 并暴露给ViewLayer
*
* @param clickLoadMore
*/
public void setLoadStatusNrefreshFooter(RecyclerAdapter.LoadStatus clickLoadMore) {
mAdapter.setLoadStatusNrefreshFooter(clickLoadMore);
}
/**
* 要再showFirstPageItems之后调用此方法
*
* @param listener
*/
public void setOnItemClickListener(Presenter.RecyclerViewOnClickListener listener) {
mAdapter.setOnItemClickListener(listener);
}
}
import java.util.ArrayList;
import java.util.List;
public class RecyclerModule {
public static boolean isLoadingMore = false;
Thread thread;
boolean shouldStop = false;
public void loadMore(int from, int length, Presenter.OnDataLoadedListener listener) {
isLoadingMore = true;
if(from > 30){
thread = new Thread() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
isLoadingMore = false;
if(shouldStop){
return;
}
listener.onDataLoadFailed(new Throwable("asdf"));
}
};
thread.start();
return;
}else{
thread = new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
List<PartBean> beanList = new ArrayList<>();
for (int i = 0; i < length; i++) {
PartBean partBean0 = new PartBean();
partBean0.title = "asdf" + (from + i);
beanList.add(partBean0);
}
isLoadingMore = false;
if(shouldStop){
return;
}
listener.onDataLoaded(beanList);
}
};
thread.start();
}
}
public void cancelAll(){
shouldStop = true;
if(thread != null){
thread.interrupt();
}
}
}
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.yds.tingli.R;
import java.util.List;
public class ViewLayer {
private PullUpRecyclerController mRecyclerController;
private View mView;
private TextView mErrorTextView;
private ProgressBar mProgressBar;
Context context;
public ViewLayer(Context context) {
this.context = context;
LayoutInflater inflater = LayoutInflater.from(context);
mView = inflater.inflate(R.layout.fraglayout, null);
RecyclerView recyclerView = (RecyclerView) mView
.findViewById(R.id.recyclerView);
mRecyclerController = new PullUpRecyclerController(context,
recyclerView);
mErrorTextView = (TextView) mView.findViewById(R.id.errorView);
mProgressBar = (ProgressBar) mView.findViewById(R.id.loadingView);
}
/**
* 第一次showContent之前一定要先调用这个方法
*
* @param mOnNeedLoadListener
*/
public void setOnNeedLoadListener(PullUpRecyclerController.OnNeedLoadListener mOnNeedLoadListener) {
mRecyclerController.setOnNeedLoadListener(mOnNeedLoadListener);
}
public View getInnerView() {
return mView;
}
public void showLoading() {
mErrorTextView.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
}
/**
* 在显示第一页的时候调用,之后就没再调用了
*
* @param beanList
* @param onclickListener
*/
public void showFirstPageContent(List<PartBean> beanList,
Presenter.RecyclerViewOnClickListener onclickListener) {
// mErrorTextView.setVisibility(View.INVISIBLE);
Log.e("aaaaaaaaaa", "showFirstPageContent: 不可见" );
mProgressBar.setVisibility(View.INVISIBLE);
mRecyclerController.showFirstpageItems(beanList);
mRecyclerController.setOnItemClickListener(onclickListener);
}
public void showError(Throwable e) {
Log.e("aaaaaaaaaa", "showFirstPageContent: 不可见2" );
mProgressBar.setVisibility(View.INVISIBLE);
mErrorTextView.setVisibility(View.VISIBLE);
}
public void showMoreContent(List<PartBean> cardViewBeanList) {
mRecyclerController.showMoreItems(cardViewBeanList);
}
public void setLoadStatusNrefreshFooter(RecyclerAdapter.LoadStatus clickLoadMore) {
mRecyclerController.setLoadStatusNrefreshFooter(clickLoadMore);
}
/**
* 加载更多未获取到数据时调用此方法
*/
public void showLoadMoreFailure() {
}
}
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.yds.tingli.R;
import java.util.List;
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int VIEW_TYPE_FOOTER = 0;
private static final int VIEW_TYPE_ITEM = 1;
private List<PartBean> mList;
private LayoutInflater mInflater;
private Context mContext;
private LoadStatus mLoadStatus = LoadStatus.DRAG_UP_TO_LAOD_MORE;
private Presenter.RecyclerViewOnClickListener mOnItemClickListener;
private RecyclerModule mForData = new RecyclerModule();
public RecyclerAdapter(Context context, List<PartBean> list) {
this.mContext = context;
mInflater = LayoutInflater.from(context);
this.mList = list;
}
@Override
public int getItemCount() {
return mList.size() + 1;
}
@Override
public int getItemViewType(int position) {
if (position + 1 == getItemCount()) {// 最后一条数据
return VIEW_TYPE_FOOTER;
} else {
return VIEW_TYPE_ITEM;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case VIEW_TYPE_FOOTER:
onBindFooterViewHolder(holder, position, mLoadStatus);
break;
case VIEW_TYPE_ITEM:
onBindItemViewHolder(holder, position);
break;
default:
break;
}
}
private void onBindFooterViewHolder(RecyclerView.ViewHolder holder, int position,
LoadStatus mLoadStatus2) {
FooterViewHolder viewHolder = (FooterViewHolder) holder;
switch (mLoadStatus2) {
case DRAG_UP_TO_LAOD_MORE:
viewHolder.mLoadingLayout.setVisibility(View.GONE);
viewHolder.mClickLoad.setVisibility(View.VISIBLE);
break;
case LOADING_MORE:
viewHolder.mLoadingLayout.setVisibility(View.VISIBLE);
viewHolder.mClickLoad.setVisibility(View.GONE);
break;
case LOAD_FAILED:
break;
case LOAD_END:
break;
}
}
private void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
ItemViewHolder viewHolder = (ItemViewHolder) holder;
viewHolder.cardView.setName(mList.get(position).title);
}
// ===================onCreateHolder below==================
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_FOOTER) {
return onCreateFooterViewHolder(parent, viewType);
} else if (viewType == VIEW_TYPE_ITEM) {
return onCreateItemViewHolder(parent, viewType);
} else {
return null;
}
}
private RecyclerView.ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
AppMainCardView view = new AppMainCardView(mContext);
return new ItemViewHolder(view, mOnItemClickListener);
}
private RecyclerView.ViewHolder onCreateFooterViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.item_footer, null);
return new FooterViewHolder(view);
}
/**
* 普通item的条目的holder
*
* @author administrator1
*/
class ItemViewHolder extends RecyclerView.ViewHolder {
private AppMainCardView cardView;
private Presenter.RecyclerViewOnClickListener mListener;
public ItemViewHolder(View view, Presenter.RecyclerViewOnClickListener listener) {
super(view);
cardView = (AppMainCardView) view;
this.mListener = listener;
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null) {
int pos = getLayoutPosition();
v.setTag(mList.get(pos));
// mListener.onItemClicked(v, getPosition());// 应该用getlayoutposition?
mListener.onItemClicked(v, pos);// 应该用getlayoutposition?
}
}
});
}
}
class FooterViewHolder extends RecyclerView.ViewHolder {
public LinearLayout mLoadingLayout;
public TextView mClickLoad;
public FooterViewHolder(View itemView) {
super(itemView);
mLoadingLayout = (LinearLayout) itemView.findViewById(R.id.loading);
mClickLoad = (TextView) itemView.findViewById(R.id.click_load_txt);
mClickLoad.setOnClickListener(new View.OnClickListener() {// 添加点击加载更多监听
@Override
public void onClick(View v) {
}
});
}
}
// ===========================method about data=========
/**
* 唯一的实现刷新效果的,就这两行语句实现刷新效果
*
* @param list
*/
public void addAllNRefresh(List<PartBean> list) {
this.mList.addAll(list);
notifyDataSetChanged();
}
public void reSetData(List<PartBean> list) {
this.mList = list;
notifyDataSetChanged();
}
/**
* 设置Adapter的状态并且刷新footer 被controller调用
*
* @param status
*/
public void setLoadStatusNrefreshFooter(LoadStatus status) {
this.mLoadStatus = status;
this.notifyItemChanged(getItemCount() - 1);
}
public enum LoadStatus {
DRAG_UP_TO_LAOD_MORE, // 点击加载更多
LOADING_MORE, // 正在加载更多
LOAD_FAILED, LOAD_END
}
/**
* 设置点击事件
*
* @param listener
*/
public void setOnItemClickListener(@NonNull Presenter.RecyclerViewOnClickListener listener) {
mOnItemClickListener = listener;
}
}
import android.app.Activity;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.yds.tingli.MainApplication;
import com.yds.tingli.PlayActivity;
import java.util.List;
public class Presenter {
ViewLayer mViewLayer;
RecyclerModule mRecyclerModule = new RecyclerModule();
public Presenter(ViewLayer viewLayer) {
this.mViewLayer = viewLayer;
/**
* 设置加载更多的监听回调
*/
mViewLayer.setOnNeedLoadListener(new PullUpRecyclerController.OnNeedLoadListener() {
@SuppressWarnings("static-access")
@Override
public void loadMore(int from, int length) {
Log.e("Presenter", "OnNeedloadMore");
mRecyclerModule.loadMore(from, length,
new OnDataLoadedListener() {
@Override
public void onDataLoaded(
final List<PartBean> cardViewBeanList) {
// 加载更多成功
((Activity) (mViewLayer.context)).runOnUiThread(new Runnable() {
@Override
public void run() {
mViewLayer.showMoreContent(cardViewBeanList);
mViewLayer.setLoadStatusNrefreshFooter(RecyclerAdapter.LoadStatus.DRAG_UP_TO_LAOD_MORE);
}
});
}
@Override
public void onDataLoadFailed(Throwable e) {
((Activity) (mViewLayer.context)).runOnUiThread(new Runnable() {
@Override
public void run() {
// 加载更多失败
Toast.makeText(
mViewLayer.getInnerView().getContext(),
"未能读取到数据", Toast.LENGTH_SHORT).show();
// mViewLayer.showError(e);
mViewLayer.showLoadMoreFailure();
mViewLayer.setLoadStatusNrefreshFooter(RecyclerAdapter.LoadStatus.DRAG_UP_TO_LAOD_MORE);
}
});
}
});
}
});
}
/**
* 方法名要改
*/
public void onActivityCreate() {
/**
* 初始化module
*/
// mModule = new Module1();
loadData(0, Constance.ITEM_IN_A_PAGE);// 这个时候加载第一页
}
public void onActivityDestroy() {
if (mRecyclerModule != null) {
mRecyclerModule.cancelAll();
}
}
/**
* 在界面初始化的时候调用这个方法 这个方法会根据情况让显示层显示loading,content或者error
*/
@SuppressWarnings("static-access")
void loadData(int from, int length) {
mViewLayer.showLoading();
// load data from module and let view show them
mRecyclerModule.loadMore(from, length, new OnDataLoadedListener() {
@Override
public void onDataLoaded(
final List<PartBean> cardViewBeanList) {
// 第一次加载成功
((Activity) (mViewLayer.context)).runOnUiThread(new Runnable() {
@Override
public void run() {
mViewLayer.showFirstPageContent(cardViewBeanList,
new RecyclerViewOnClickListener() {
@Override
public void onItemClicked(View view, int position) {
//TODO 进入下一个页面
Toast.makeText(mViewLayer.getInnerView().getContext(),
"点击" + position, Toast.LENGTH_SHORT).show();
PartBean bean = (PartBean) view.getTag();
Intent intent = new Intent(
MainApplication.getContext(),
PlayActivity.class);
intent.putExtra("bean", bean);
((Activity) (mViewLayer.context)).startActivity(intent);
}
});
}
});
}
@Override
public void onDataLoadFailed(Throwable e) {
// 第一次加载失败
Toast.makeText(mViewLayer.getInnerView().getContext(),
"未能读取到数据", Toast.LENGTH_SHORT).show();
mViewLayer.showError(e);
}
});
}
public interface OnDataLoadedListener {
void onDataLoaded(List<PartBean> beanList);
void onDataLoadFailed(Throwable e);
}
public interface RecyclerViewOnClickListener {
void onItemClicked(View v, int position);// 应该用getlayoutposition?
}
}
fraglayout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/errorView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="error"
android:textSize="30dp" />
<ProgressBar
android:id="@+id/loadingView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@color/white" />
</RelativeLayout>
itemfooter.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp">
<LinearLayout
android:id="@+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="horizontal">
<TextView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="加载"
android:textSize="30dp" />
<ProgressBar
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:id="@+id/click_load_txt"
android:text="加载更多"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
mainitem.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="title" />
</RelativeLayout>
最后在activity中使用
Presenter mPresenter;
ViewLayer mViewLayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewLayer = new ViewLayer(this);
mPresenter = new Presenter(mViewLayer);
mPresenter.onActivityCreate();
setContentView(mViewLayer.getInnerView());
}
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.onActivityDestroy();
}