您的位置:首页 > 其它

RecycleView + SwipeRefreshLayout 对adapter和刷新的封装

2016-07-12 15:43 190 查看
用了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;

4000
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.sendEmp
c552
tyMessageDelayed(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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: