软件编程
位置:首页>> 软件编程>> Android编程>> Android RecyclerView的刷新分页的实现

Android RecyclerView的刷新分页的实现

作者:零点小筑  发布时间:2022-10-31 15:40:34 

标签:RecyclerView,刷新,分页

在开发中常常使用到刷新分页,这里实现一个 RecyclerView 的简单的刷新分页操作,测试效果见文末,实现过程参考如下:

实现思路

  1. 加载更多数据使用到 RecyclerView 加载多种布局,根据 ViewType 判断加载数据 Item 还是加载 FooterItem ;

  2. 通过线程模拟加载数据;

  3. 为 RecyclerView 添加 addOnScrollListener 事件来监听用户的滑动操作;

  4. 根据用户滑动状态以及具体情况开始加载数据

  5. 通知数据更新;

如何获得 firstVisibleItemPosition

为了能够在数据加载中动态判断什么时候加载数据,需要知道屏幕上显示的第一个可见的 Item 的位置,当然了这里使用的是布局管理器是 LinearLayoutManager ,这样查找屏幕上第一个可见的 Item 就显得容易多了,下面介绍一些 LinearLayoutManager 的四个方法:

findFirstVisibleItemPosition()

获得屏幕上第一个可见 Item 的 position,只要该 Item 有一部分可见,那么返回的 position 就是该Item 的 position。

findFirstCompletelyVisibleItemPosition()

获得屏幕上第一个完整可见的 Item 的 position,只要该 Item 有一部分不可见,那么返回的 position 就是该 Item 对应的下一个能显示完整的 Item 的position。

findLastVisibleItemPosition()

获得屏幕上最后一个可见 Item 的 position,只要该 Item 有一部分可见,那么返回的 position 就是该Item 的 position。

findLastCompletelyVisibleItemPosition()

获得屏幕上最后一个完整可见的 Item 的 position,只要该 Item 有一部分不可见,那么返回的 position 就是该 Item 对应的上一个能显示完整的 Item 的position。

准备数据


/**
 * 初始化数据
 * @return
 */
public void initData(){
 for (int i=0;i<30;i++){
  arrayList.add("第"+i+"条数据");
 }
}

/**
 * 线程模拟加载数据
 */
class LoadDataThread extends Thread{
 @Override
 public void run() {
  initData();
  try {
   Thread.sleep(2000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  //通知主线程更新数据
  Message message = handler.obtainMessage();
  message.what = UPDATE_DATA;
  message.obj = arrayList;
  handler.sendMessage(message);
 }
}

代码参考

主布局


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.manu.mrecyclerview.MainActivity">
<android.support.v7.widget.RecyclerView
 android:id="@+id/rv"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>

Item布局


/**item.xml**/
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp">
<TextView
 android:id="@+id/tv_recycle"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:gravity="center_horizontal"
 android:text="data"
 android:background="#cac3c3"
 android:padding="10dp"
 android:textSize="20sp"/>
</LinearLayout>

/**item_footer.xml**/
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
<ProgressBar
 style="?android:attr/progressBarStyleSmall"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:id="@+id/progressBar" />
<TextView
 android:text="正在努力加载中,请稍后..."
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:id="@+id/textView" />
</LinearLayout>

Adapter

这里使用了 RecyclerView 根据不同的 ViewType 加载多种布局的用法,使用时根据不同的布局创建不同的 ViewHolder , 然后根据不同的 Viewholder 为对应的 Item 添加数据,注意 getItemViewType() 方法的用法,Adapter 代码参考如下:


/**
* Created by jzman on 2017/6/04
* RecycleView的Adapter
*/
public class RvAdapter1 extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements
 View.OnClickListener{
private static final int ITEM_FOOTER = 0x1;
private static final int ITEM_DATA = 0x2;
private Context mContext;
private RecyclerView recyclerView;
private ArrayList<String> mList;

public RvAdapter1() {}

public RvAdapter1(Context mContext, ArrayList<String> mList) {
 this.mContext = mContext;
 this.mList = mList;
}

public void setmList(ArrayList<String> mList) {
 this.mList = mList;
}

/**
 * 用于创建ViewHolder
 * @param parent
 * @param viewTypez
 * @return
 */
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 View view ;
 RecyclerView.ViewHolder vh = null;
 switch (viewType){
  case ITEM_DATA:
   view = LayoutInflater.from(mContext).inflate(R.layout.item,null);
   view.setOnClickListener(this);
   vh = new DataViewHolder(view);
   //使用代码设置宽高(xml布局设置无效时)
   view.setLayoutParams(new ViewGroup.LayoutParams(
     ViewGroup.LayoutParams.MATCH_PARENT,
     ViewGroup.LayoutParams.WRAP_CONTENT));
   break;
  case ITEM_FOOTER:
   view = LayoutInflater.from(mContext).inflate(R.layout.item_footer,null);
   //使用代码设置宽高(xml布局设置无效时)
   vh = new FooterViewHolder(view);
   view.setLayoutParams(new ViewGroup.LayoutParams(
     ViewGroup.LayoutParams.MATCH_PARENT,
     ViewGroup.LayoutParams.WRAP_CONTENT));
   break;
 }
 return vh;
}

/**
 * 获取Item的View类型
 * @param position
 * @return
 */
@Override
public int getItemViewType(int position) {
 //根据 Item 的 position 返回不同的 Viewtype
 if (position == (getItemCount())-1){
  return ITEM_FOOTER;
 }else{
  return ITEM_DATA;
 }
}

/**
 * 绑定数据
 * @param holder
 * @param position
 */
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
 if (holder instanceof DataViewHolder){
  DataViewHolder dataViewHolder = (DataViewHolder) holder;
  dataViewHolder.tv_data.setText(mList.get(position));
 }else if (holder instanceof FooterViewHolder){

}
}

/**
 * 选项总数
 * @return
 */
@Override
public int getItemCount() {
 return mList.size()+1;
}

@Override
public void onClick(View view) {
 //根据RecyclerView获得当前View的位置
 int position = recyclerView.getChildAdapterPosition(view);
 //程序执行到此,会去执行具体实现的onItemClick()方法
 if (onItemClickListener!=null){
  onItemClickListener.onItemClick(recyclerView,view,position,mList.get(position));
 }
}

/**
 * 创建ViewHolder
 */
public static class DataViewHolder extends RecyclerView.ViewHolder{
 TextView tv_data;
 public DataViewHolder(View itemView) {
  super(itemView);
  tv_data = (TextView) itemView.findViewById(R.id.tv_recycle);
 }
}

/**
 * 创建footer的ViewHolder
 */
public static class FooterViewHolder extends RecyclerView.ViewHolder{
 public FooterViewHolder(View itemView) {
  super(itemView);
 }
}

private OnItemClickListener onItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
 this.onItemClickListener = onItemClickListener;
}

/**
 * 定义RecyclerView选项单击事件的回调接口
 */
public interface OnItemClickListener{
 //参数(父组件,当前单击的View,单击的View的位置,数据)
 void onItemClick(RecyclerView parent,View view, int position, String data);
}
/**
 * 将RecycleView附加到Adapter上
 */
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
 super.onAttachedToRecyclerView(recyclerView);
 this.recyclerView= recyclerView;
}
/**
 * 将RecycleView从Adapter解除
 */
@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
 super.onDetachedFromRecyclerView(recyclerView);
 this.recyclerView = null;
}
}

MainActivity

这里主要注意 rv.addOnScrollListener(new OnScrollListener() ...里面的具体实现,MainActivity 代码参考如下:


/**
* Created by jzman on 2017/6/04 0013.
*/
public class MainActivity extends AppCompatActivity {
private static final int UPDATE_DATA = 0x3;

private RecyclerView rv;
RvAdapter1 adapter;

private ArrayList<String> arrayList = new ArrayList<>();
//加载更多数据时最后一项的索引
private int lastLoadDataItemPosition;

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 rv = (RecyclerView) findViewById(R.id.rv);

//设置布局管理器
 rv.setLayoutManager(new LinearLayoutManager(this));//线性
//  rv.setLayoutManager(new GridLayoutManager(this,4));//线性
//  rv.setLayoutManager(new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.VERTICAL));//线性
 initData();
 adapter = new RvAdapter1(this,arrayList);
 adapter.setOnItemClickListener(new RvAdapter1.OnItemClickListener() {
  @Override
  public void onItemClick(RecyclerView parent, View view, int position, String data) {
   Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show();
  }
 });

rv.addOnScrollListener(new OnScrollListener() {
  @Override
  public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
   if (newState == SCROLL_STATE_IDLE &&
     lastLoadDataItemPosition == adapter.getItemCount()){
    new LoadDataThread().start();
   }
  }

@Override
  public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

LayoutManager layoutManager = recyclerView.getLayoutManager();
   if (layoutManager instanceof LinearLayoutManager){
    LinearLayoutManager manager = (LinearLayoutManager) layoutManager;
    int firstVisibleItem = manager.findFirstVisibleItemPosition();
    int l = manager.findLastCompletelyVisibleItemPosition();
    lastLoadDataItemPosition = firstVisibleItem+(l-firstVisibleItem)+1;
   }
  }
 });

rv.setAdapter(adapter);
}

/**
 * 初始化数据
 * @return
 */
public void initData(){
 for (int i=0;i<25;i++){
  arrayList.add("第"+i+"条数据");
 }
}

/**
 * 线程模拟加载数据
 */
class LoadDataThread extends Thread{
 @Override
 public void run() {
  initData();
  try {
   Thread.sleep(2000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  Message message = handler.obtainMessage();
  message.what = UPDATE_DATA;
  message.obj = arrayList;
  handler.sendMessage(message);
 }
}

private Handler handler = new Handler(){

@Override
 public void handleMessage(Message msg) {
  super.handleMessage(msg);
  switch (msg.what){
   case UPDATE_DATA:
    arrayList = (ArrayList<String>) msg.obj;
    adapter.setmList(arrayList);
    adapter.notifyDataSetChanged();
    break;
  }
 }
};
}

测试效果

Android RecyclerView的刷新分页的实现

来源:https://www.jianshu.com/p/9a540babacf0

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com