小弟之前做了一段时间管理,而对于RecyclerView这强大的控件用的少,最近又回到了码农的世界,写的不好还望大家不要见怪,谢谢。大家应该都知道RecyclerView的强大之处,这里也就不多言了。这几天公司开发一个新的项目,自己用了到一个开源的SuperRecyclerView;这里附上github上的链接:https://github.com/supercwn/SuperRecycleView
不得不说这个控件还是很好用的,尤其是对Adapter的封装,使用起来代码简洁,方便:
public class BRAllAdapter extends SuperBaseAdapter<BRAllInfo.BRAllDatasInfo> { private Context mContext; public BRAllAdapter(Context context, List<BRAllInfo.BRAllDatasInfo> data) { super(context, data); this.mContext = context; } @Override protected void convert(BaseViewHolder holder, BRAllInfo.BRAllDatasInfo item, int position) { holder.setText(R.id.tv_br_title, item.getGame_name()); holder.setText(R.id.tv_br_price, "-" + item.getPrice() + mContext.getResources().getString(R.string.string_element)); holder.setText(R.id.tv_br_qishu, item.getQishu() + mContext.getResources().getString(R.string.string_periods)); holder.setText(R.id.tv_br_time, item.getTz_time()); holder.setText(R.id.tv_br_status, setText(item.getStatus(), item)); holder.setTextColor(R.id.tv_br_status, setTextColor(item.getStatus(), item)); } @Override protected int getItemViewLayoutId(int position, BRAllInfo.BRAllDatasInfo item) { return R.layout.item_br_all; } }绑定你的bean数据后,在onvert里面通过封装好的set方法来设置你想要的界面数据,用起来还是很爽的;
好了,来说一下这个控件踩到的坑
我在项目中把上拉加载到的新数据添加到集合集合当中,然后调用了notifyDataSetChanged刷新RecyclerView,OK没有问题,我们的数据都是正常加载显示;然而这时在下拉刷新的时候,抛出了 java.lang.IllegalArgumentException: Scrapped or attached views may not be recycled. isScrap:false isAttached:true com.superrecycleview.superlibrary.recycleview.SuperRecyclerView 这段异常,跟着代码Debug了一遍,所有的流程走下来没有任何问题,就是在调用刷新notify的时候界面崩溃,仔细检查了好多遍,网络请求数据>清空数据列表>获取网络数据>添加新数据到集合>调用notify刷新界面,逻辑上一点问题都没,感到有点莫名其妙,不像空指针异常,找不到出错的地方,无奈求助了一下谷歌,百度,基本上说的是animateLayoutChanges与RecyclerView刷新共用所导致,然而我的代码并没有使用到animateLayoutChanges;后来还是决定去看下onRefresh方法的源码:
@Override public boolean onTouchEvent(MotionEvent ev) { if (mLastY == -1) { mLastY = ev.getRawY(); } switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mLastY = ev.getRawY(); break; case MotionEvent.ACTION_MOVE: final float deltaY = ev.getRawY() - mLastY; mLastY = ev.getRawY(); if (isOnTop() && refreshEnabled && appbarState == AppBarStateChangeListener.State.EXPANDED) { mRefreshHeader.onMove(deltaY / DRAG_RATE); if (mRefreshHeader.getVisibleHeight() > 0 && mRefreshHeader.getState() < ArrowRefreshHeader.STATE_REFRESHING) { return false; } } break; default: mLastY = -1; // reset if (isOnTop() && refreshEnabled && appbarState == AppBarStateChangeListener.State.EXPANDED) { if (mRefreshHeader.releaseAction()) { if (mLoadingListener != null) { mLoadingListener.onRefresh(); } } } break; } return super.onTouchEvent(ev); }
看到只有在onTouchEvent方法里面做了刷新监听的处理,通过这段判断逻辑找到了问题的原因:我在请求数据之前,也就是在onRefresh里面先将原来的数据清空,然后再获取网络接口的数据,而从清空数据到获取到数据的这段时间里,List中的数据是不存在的,所以给了RecyclerView要回收Item,但是View没有被回收的假象(此时并没有执行notifyDataSetChanged()方法),因此抛出了上述异常;找到问题原因就好解决了,接下来将list.clear()放在获取新数据之后,添加数据之前清空数据,问题得到解决!!!
对于上述解决问题方法仅供参考,如有问题欢迎大家指正,谢谢大家!!!!