浅谈SuperRecyclerView的踩坑

本文介绍了一个好用的RecyclerView封装——SuperRecyclerView,并分享了在实际项目中遇到的问题及解决方案。作者详细解析了Adapter的使用方法,并针对上拉加载、下拉刷新时出现的异常情况进行了深入分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小弟之前做了一段时间管理,而对于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()放在获取新数据之后,添加数据之前清空数据,问题得到解决!!!


对于上述解决问题方法仅供参考,如有问题欢迎大家指正,谢谢大家!!!!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值