RecycleView + SwipeRefreshLayout 对adapter和刷新的封装

来源:互联网 发布:宁波楼市每日成交数据 编辑:程序博客网 时间:2024/05/06 12:24

用了recycleview一段时间了,感觉效果很不错,但是就是adapter的写法太过于复杂,并且配合谷歌官方的SwipeRefreshLayout使用很是复杂。今天就对其进行一次封装。

1.首先recycleview是强制需要viewholder模式的,所以我们对其viewholder的封装是必须的;

/** * Created by zhenfei.wang on 2016/7/12. * recycleview的通用ViewHolder */public class RcyViewHolder extends RecyclerView.ViewHolder{    private SparseArray<View> mViews;    private View mConvertView;    private Context mContext;    public RcyViewHolder(Context context, View itemView, ViewGroup parent)    {        super(itemView);        mContext = context;        mConvertView = itemView;        mViews = new SparseArray<View>();    }    public static RcyViewHolder get(Context context, ViewGroup parent, int layoutId)    {        View itemView = LayoutInflater.from(context).inflate(layoutId, parent,                false);        RcyViewHolder holder = new RcyViewHolder(context, itemView, parent);        return holder;    }    /**     * 通过viewId获取控件     *     * @param viewId     * @return     */    public <T extends View> T getView(int viewId)    {        View view = mViews.get(viewId);        if (view == null)        {            view = mConvertView.findViewById(viewId);            mViews.put(viewId, view);        }        return (T) view;    }

2.其次是封装通用的CommontAdapter;

/** * Created by zhenfei.wang on 2016/7/12. * recycleview 通用的Adapter * 只支持单一布局 */public abstract class RcyCommonAdapter <T> extends RecyclerView.Adapter<RcyViewHolder>{    protected Context mContext;    protected int mLayoutId;    protected List<T> mDatas;    protected LayoutInflater mInflater;    protected boolean loadMore;    /**     *     * @param context     * @param layoutId     * @param datas     * @param loadMore 是否需要底部加载更多     * @param rv     */    public RcyCommonAdapter(Context context, int layoutId, List<T> datas , boolean loadMore,RecyclerView rv)    {        mContext = context;        mInflater = LayoutInflater.from(context);        mLayoutId = layoutId;        mDatas = datas;        this.loadMore = loadMore;        setSpanCount(rv);    }    /**     * 设置每个条目占用的列数     * @param recyclerView recycleView     */    private void setSpanCount(RecyclerView recyclerView) {        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();        if (layoutManager instanceof GridLayoutManager) {            final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {                @Override                public int getSpanSize(int position) {                    int type = getItemViewType(position);                    // 若是最后一个 且需要加载更多,则强制让最后一个条目占满横屏                    if (type == R.layout.item_list_footer) {                        return gridLayoutManager.getSpanCount();                    } else {                        return 1;                    }                }            });        }    }    @Override    public RcyViewHolder onCreateViewHolder(final ViewGroup parent, int viewType)    {        return RcyViewHolder.get(mContext, parent, viewType);    }    @Override    public int getItemViewType(int position) {        int lId = 0;        if(loadMore && position + 1 == getItemCount()){            lId = R.layout.item_list_footer;        } else {            lId = getmLayoutId(position);        }        return lId;    }    @Override    public void onBindViewHolder(RcyViewHolder holder, int position)    {        if(getItemViewType(position)  == R.layout.item_list_footer){            checkLoadStatus(holder);        }else {            convert(holder, mDatas.get(position));        }    }    private void checkLoadStatus(RcyViewHolder holder) {        if(getItemCount() != 1){             holder.getView(R.id.tv_item_footer_load_more).setVisibility(View.GONE);             holder.getView(R.id.pb_item_footer_loading).setVisibility(View.VISIBLE);        }else {            holder.getView(R.id.tv_item_footer_load_more).setVisibility(View.GONE);            holder.getView(R.id.pb_item_footer_loading).setVisibility(View.GONE);        }    }    public abstract void convert(RcyViewHolder holder, T t);    public abstract int getmLayoutId(int position);    @Override    public int getItemCount()    {        return  loadMore ? mDatas.size() + 1 : mDatas.size();    }}
3.使用方法,我们写个简单的TestAdapter,可见只要复写两个方法,第一就是为不同的位置数据适配不同的布局资源,第二个就是数据适配

/** * Created by zhenfei.wang on 2016/7/12. */public class TestAdapter extends RcyCommonAdapter<String> {    public TestAdapter(Context context, int layoutId, List datas , boolean loadMore, RecyclerView rv) {        super(context, layoutId, datas, loadMore, rv);    }    @Override    public int getmLayoutId(int position) {        return position % 2 == 0 ? R.layout.item1 : R.layout.item2;    }    @Override    public void convert(RcyViewHolder holder, String s) {        TextView tv = holder.getView(R.id.tv);        tv.setText(s);    }}
4.提供一下我们的主Activity和其布局;

public class MainActivity extends Activity implements SwipeRefreshLayout.OnRefreshListener{    private RecyclerView rv;    private SwipeRefreshLayout refreshLayout;    private LinearLayoutManager layoutManager;    private List<String> data;    private TestAdapter adapter;    private Handler handler = new Handler(){        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            switch (msg.what){                case 0:                    Utils.refresh(data);                    adapter.notifyDataSetChanged();                    refreshLayout.setRefreshing(false);                    break;                case 1:                    Utils.loadMore(data);                    adapter.notifyDataSetChanged();                    break;                default:                    break;            }        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        rv = (RecyclerView) findViewById(R.id.rv);        refreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh_layout);        init();    }    private void init() {        data = new ArrayList<String>();        layoutManager = new LinearLayoutManager(this);//        layoutManager = new GridLayoutManager(this, 2);        refreshLayout.setOnRefreshListener(this);        rv.setLayoutManager(layoutManager);        adapter = new TestAdapter(this, R.layout.item1, data, true, rv);        rv.addOnScrollListener(new OnRecyclerScrollListener(adapter, refreshLayout, layoutManager) {
    // 加载更多数据            @Override            public void loadMore() {                handler.sendEmptyMessageDelayed(1, 2000);            }        });        rv.setAdapter(adapter);        refreshLayout.setRefreshing(true);        onRefresh();    }
    // 数据刷新    @Override    public void onRefresh() {        handler.sendEmptyMessageDelayed(0, 2000);    }

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <android.support.v4.widget.SwipeRefreshLayout        android:id="@+id/refresh_layout"        android:layout_width="match_parent"        android:layout_height="match_parent">        <android.support.v7.widget.RecyclerView            android:id="@+id/rv"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:background="#93BBBB" />    </android.support.v4.widget.SwipeRefreshLayout></RelativeLayout>

5.可以看到我们把RecyclerView.OnScrollListener封装成自己的,我们只需要上拉加载更多的事件传出来即可,其他的不想看到,可以用一个抽象方法搞定;

/** * Created by zhenfei.wang on 2016/7/12. * recycle的滑动监听,上拉加载更多操作 */public abstract class OnRecyclerScrollListener extends RecyclerView.OnScrollListener{    private int lastVisibleItem = 0;    private RecyclerView.Adapter mAdapter;    private SwipeRefreshLayout refreshLayout;    private LinearLayoutManager layoutManager;    public OnRecyclerScrollListener(RecyclerView.Adapter mAdapter, SwipeRefreshLayout refreshLayout, LinearLayoutManager layoutManager) {        this.mAdapter = mAdapter;        this.refreshLayout = refreshLayout;        this.layoutManager = layoutManager;    }    @Override    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {        super.onScrollStateChanged(recyclerView, newState);        //如果滚动到底部,就获取更多的数据        if (mAdapter != null && newState == RecyclerView.SCROLL_STATE_IDLE && lastVisibleItem + 1 == mAdapter.getItemCount()) {            if (!refreshLayout.isRefreshing()) {                loadMore();            }        }    }    @Override    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {        super.onScrolled(recyclerView, dx, dy);        lastVisibleItem = layoutManager.findLastVisibleItemPosition();    }    public abstract void loadMore();}

想要项目的可以去我的github下载:https://github.com/179576267/RecycleView-swipeRefreshLayout/tree/1.0

0 0
原创粉丝点击