RecyclerView的上拉自动加载

来源:互联网 发布:php 新特性 好处 编辑:程序博客网 时间:2024/05/21 02:36

最近自己做一个小项目的时候遇到了RecyclerView的上拉加载问题,之前ListView用多了,上拉加载也有很完善的库了,可是RecyclerView我在Github上搜了一搜,没发现有特别好,特别完善的库,所以我就自己网上找了一些资料。然后自己尝试去写,结果悲剧的发现,RecyclerView最关键的居然是Adapter和ViewHolder,所以我就先从这两个入手。

首先是ViewHolder,大家都知道,RecyclerView中已经有了ViewHolder类了,所以我们可以简单封装一下,就想ListView的万能ViewHolder一样封装一下:

import android.content.Context;import android.support.v7.widget.RecyclerView;import android.util.SparseArray;import android.view.View;import android.widget.TextView;public class BaseViewHolder extends RecyclerView.ViewHolder {    private SparseArray<View> mViews;//集合类,layout里包含的View,以view的id作为key,value是view对象    private Context mContext;//上下文对象    public BaseViewHolder(Context context,View itemView) {        super(itemView);        mContext = context;        mViews = new SparseArray<>();    }    //通过View的id获得View    public <T extends View> T getView(int viewId){        //从集合中找View,找不到再去itemView中findViewById然后添加在集合类中        View view = mViews.get(viewId);        if (view == null){            view = itemView.findViewById(viewId);            mViews.put(viewId,view);        }        return (T)view;    }    //通过TextView的Id找到TextView然后直接设置TextView的Text属性    public BaseViewHolder setText(int viewId,String value){        TextView textView = getView(viewId);        textView.setText(value);        return this;    }    //通过TextView的Id找到TextView然后直接设置TextView的Text属性    public BaseViewHolder setText(int viewId,int resId){        TextView textView = getView(viewId);        textView.setText(resId);        return this;    }}
对ViewHolder做了一下简单的封装,然后接下来就是重点了,写一个抽象的Adapter集成RecyclerView.Adapter,为了更好的使用,我们把这个Adapter做的全面一点,支持Header和Footer,下面就直接贴代码吧:
import android.content.Context;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import java.util.List;public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {    private Context mContext;    private int mLayoutId;    private List<T> mDatas;    private LayoutInflater mInflater;    private boolean isLoading = false;    private OnItemClickListener mClickListener;    private OnItemLongClickListener mLongClickListener;    private OnLoadMoreListener mOnLoadMoreListener;    private View mHeaderViwe;    private boolean HaveMoreData = true;    private TextView LoadText;    /**     * 声明Item的状态     */    private final static int TYPE_HEADVIEW=100;    private final static int TYPE_ITEM=101;    private final static int TYPE_FOOTER=102;    public BaseRecyclerAdapter(Context context, RecyclerView recyclerView, List<T> datas, int layoutId){        this.mLayoutId = layoutId;        this.mDatas = datas;        this.mContext = context;        mInflater = LayoutInflater.from(context);        init(recyclerView);    }    //获取Item总数    @Override    public int getItemCount() {        return mDatas.size() + 1;    }    @Override    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        //根据viewType去判断Item的类型,创建相对应的ViewHolder        if (viewType == TYPE_ITEM){            View itemView = mInflater.inflate(mLayoutId,parent,false);            BaseViewHolder holder = new BaseViewHolder(mContext,itemView);            return holder;        }else if (viewType == TYPE_HEADVIEW){            HeaderViewHolder headViewHolder=new HeaderViewHolder(mHeaderViwe);            return headViewHolder;        }        else{            View progressView = mInflater.inflate(R.layout.list_foot_loading,parent,false);            ProgressViewHolder progressHolder = new ProgressViewHolder(progressView);            return progressHolder;        }    }    /**     * 通过position判断返回的Item的类型     * @param position 索引     * @return 100返回的是头部布局,101返回的是数据源布局,102返回的是底部布局     */    @Override    public int getItemViewType(int position) {        //判断mHeaderView是否为空决定是否要添加头部布局        if (mHeaderViwe!=null){            if (position==getItemCount()-1){                return TYPE_FOOTER;            }else if (position==0){                return TYPE_HEADVIEW;            }else {                return TYPE_ITEM;            }        }else {            if (position==getItemCount()-1){                return TYPE_FOOTER;            }else {                return TYPE_ITEM;            }        }    }    @Override    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {        if (holder instanceof BaseViewHolder){            //提醒用户复写此方法            conver(mContext,holder,mDatas.get(position));            //注册点击事件            holder.itemView.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    mClickListener.onItemClick(v,position);                }            });            //注册长按事件            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {                @Override                public boolean onLongClick(View v) {                    mLongClickListener.onItemLongClick(v,position);                    return true;                }            });        }    }    private void init(RecyclerView recyclerView){        //为RecyclerView添加滚动监听事件        recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {            @Override            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {                super.onScrolled(recyclerView, dx, dy);                LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();                //获得Item的总数                int totalItemCount = linearLayoutManager.getItemCount();                //获得最后一项的索引                int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();                if (HaveMoreData && !isLoading && dy > 0 && lastVisibleItemPosition >= totalItemCount - 1){                    //此时是刷新状态                    if (mOnLoadMoreListener != null){                        mOnLoadMoreListener.OnLoadMore();                    }                    isLoading = true;                }            }        });    }    public void updateData(List<T> data) {        mDatas.clear();        mDatas.addAll(data);        notifyDataSetChanged();    }    public void addAll(List<T> datas){        mDatas.addAll(datas);        notifyDataSetChanged();    }    /**     * 加载更多ViewHolder     */    public class ProgressViewHolder extends RecyclerView.ViewHolder{        public ProgressViewHolder(View itemView) {            super(itemView);            LoadText = (TextView) itemView.findViewById(R.id.load_text);        }    }    /**     * 头部ViewHolder     */    public class HeaderViewHolder extends RecyclerView.ViewHolder{        public HeaderViewHolder(View itemView) {            super(itemView);        }    }    /**     * 声明接口     */    public interface OnItemClickListener{        public void onItemClick(View view,int position);    }    public interface OnItemLongClickListener{        public void onItemLongClick(View view,int position);    }    public interface OnLoadMoreListener{        public void OnLoadMore();    }    /**     * 设置监听事件     */    public void setClickListener(OnItemClickListener clickListener) {        mClickListener = clickListener;    }    public void setLongClickListener(OnItemLongClickListener longClickListener) {        mLongClickListener = longClickListener;    }    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {        mOnLoadMoreListener = onLoadMoreListener;    }    public void setLoading(boolean loading) {        isLoading = loading;    }    public void setHaveMoreData(boolean haveMoreData) {        HaveMoreData = haveMoreData;        //必须判断一下LoadText是否为空,因为一进入App时刷新布局并没有创建这LoadText        if (LoadText != null) {            if (!haveMoreData) {                LoadText.setText("没有更多了");            } else {                LoadText.setText("正在加载....");            }        }    }    public void addHeader(View headerViwe){        this.mHeaderViwe = headerViwe;    }    /**     * 声明抽象事件     */    public abstract void conver(Context context,RecyclerView.ViewHolder holder,T t);}



这样就把RecyclerView最重要的Adapter和ViewHolder写好了。
目前这个Adapter只适用于LinearLayoutManager布局,我会继续研究一下其他布局。。

然后就是使用了,使用的话,相对就简单一点啦,因为该封装的都封装了:
Adapter.java:
import android.content.Context;import android.support.v7.widget.RecyclerView;import java.util.List;public class Adapter extends BaseRecyclerAdapter<String> {    public Adapter(Context context, RecyclerView recyclerView, List<String> datas, int layoutId) {        super(context, recyclerView, datas, layoutId);    }    @Override    public void conver(Context context, RecyclerView.ViewHolder holder, String s) {        //必须要判断holder是否是BaseViewHolder实例,不然会有可能导致布局混乱        if (holder instanceof BaseViewHolder){            ((BaseViewHolder) holder).setText(R.id.tv,s);        }    }}
MainActivity.java
import android.os.Bundle;import android.support.v4.widget.SwipeRefreshLayout;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.View;import android.widget.Toast;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity {    private RecyclerView mRecyclerView;    private Adapter mAdapter;    private List<String> mDatas = new ArrayList<>();    private int page=0;    private SwipeRefreshLayout refreshLayout;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //初始化布局        mRecyclerView = (RecyclerView) findViewById(R.id.rv);        refreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh);        //设置RecyclerView布局        LinearLayoutManager layout = new LinearLayoutManager(this);        mRecyclerView.setLayoutManager(layout);        //初始化Adapter        mAdapter = new Adapter(this,mRecyclerView,mDatas,R.layout.list_item);        //为RecyclerView绑定适配器        mRecyclerView.setAdapter(mAdapter);        //添加上啦加载更多事件监听        mAdapter.setOnLoadMoreListener(new BaseRecyclerAdapter.OnLoadMoreListener() {            @Override            public void OnLoadMore() {                page++;                //新建一个线程去执行                new Thread(){                    @Override                    public void run() {                        super.run();                        try {                            Thread.sleep(1000);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                        final List<String> data = new ArrayList<String>();                        for (int i = 0; i < 6; i++) {                            data.add("page" + page + "item" + i);                        }                        //使用UI线程去执行添加数据操作                        //addData()是在自定义的Adapter中自己添加的方法,用来给list添加数据                        runOnUiThread(new Runnable() {                            @Override                            public void run() {                                if(mDatas.size() <= 30) {                                    mAdapter.addAll(data);                                    mAdapter.setLoading(false);                                }                                else{                                    mAdapter.setHaveMoreData(false);                                    mAdapter.setLoading(false);                                }                            }                        });                    }                }.start();            }        });        //添加Item的点击事件监听        mAdapter.setClickListener(new BaseRecyclerAdapter.OnItemClickListener() {            @Override            public void onItemClick(View view, int position) {                Toast.makeText(MainActivity.this, "this is "+position, Toast.LENGTH_SHORT).show();            }        });        //添加下拉刷新的事件监听        refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {            @Override            public void onRefresh() {                //新建一个线程去执行                new Thread(){                    @Override                    public void run() {                        super.run();                        try {                            Thread.sleep(1000);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                        final List<String> data = new ArrayList<String>();                        for (int i = 0; i < 10; i++) {                            data.add("refresh item"+i);                        }                        //使用UI线程去执行数据更新操作                        runOnUiThread(new Runnable() {                            @Override                            public void run() {                                //调用adapter中定义的更新数据的方法                                mAdapter.updateData(data);                                refreshLayout.setRefreshing(false);                                //设置一下HaveMoreData的                                mAdapter.setHaveMoreData(true);                            }                        });                    }                }.start();            }        });        //初始化mData的数据        for (int i=0;i<=9;i++){            mDatas.add("item"+i);        }    }}

我写的这个例子是避免了重写RecyclerView,而通过Adapter去实现了上拉加载的方法,所以Adapter初始化的时候要把RecyclerView加进去,这个例子还有很多东西没有完善,但是基本的都有了,可以多多参考一下。有问题欢迎我们一起讨(tao)论(lu)一下!!





0 0
原创粉丝点击