RecyclerView的刷新分页

来源:互联网 发布:数据库命令导入dmp文件 编辑:程序博客网 时间:2024/06/06 17:33

在开发中常常使用到刷新分页,这里实现一个 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;            }        }    };}

测试效果

image


<完>