用了recycleview一段时间了,感觉效果很不错,但是就是adapter的写法太过于复杂,并且配合谷歌官方的SwipeRefreshLayout使用很是复杂。今天就对其进行一次封装。
1.首先recycleview是强制需要viewholder模式的,所以我们对其viewholder的封装是必须的;
/** * Created by zhenfei.wang on 2016/7/12. * recycleview的通用ViewHolder */ public class RcyViewHolder extends RecyclerView.ViewHolder{ private SparseArraymViews; private View mConvertView; private Context mContext; public RcyViewHolder(Context context, View itemView, ViewGroup parent) { super(itemView); mContext = context; mConvertView = itemView; mViews = new SparseArray (); } 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.Adapter3.使用方法,我们写个简单的TestAdapter,可见只要复写两个方法,第一就是为不同的位置数据适配不同的布局资源,第二个就是数据适配{ 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(); } }
/** * Created by zhenfei.wang on 2016/7/12. */ public class TestAdapter extends RcyCommonAdapter4.提供一下我们的主Activity和其布局;{ 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); } }
public class MainActivity extends Activity implements SwipeRefreshLayout.OnRefreshListener{ private RecyclerView rv; private SwipeRefreshLayout refreshLayout; private LinearLayoutManager layoutManager; private Listdata; 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 (); 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); }
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:id="@+id/refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#93BBBB" />
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