侧边栏壁纸
博主头像
DevWiki博主等级

不怕慢,只怕站!

  • 累计撰写 156 篇文章
  • 累计创建 90 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

RecyclerView问题记录

DevWiki
2016-07-19 / 0 评论 / 0 点赞 / 10 阅读 / 6319 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2024-03-31,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

本文记录在使用 RecyclerView过程中遇到的各种问题,不定时更新而且尽量会同步至RecyclerVie项目的issues中。如果有任何疑问或者问题欢迎在github上添加issue

使用方法相关问题

1.在上一篇的Adapter和ViewHolder的封装一文中,如果列表中的多个ViewHolder没有任何关系,构建Adapter如何传递依赖的ViewHolder类型?

解决:

直接传递ViewHolder的父类 BaseHolder,然后在onBindCustomViewHolder时强制转换为相应的ViewHolder。
详细的代码参见MutltiAdapter,主要代码如下所示:

@Override
public BaseHolder createCustomViewHolder(ViewGroup parent, int viewType) {
    if (viewType == VIEW_TEXT) {
        return new TextHolder(parent, R.layout.item_multi_text);
    } else {
        return new ImageHolder(parent, R.layout.item_multi_image);
    }
}

@Override
public void bindCustomViewHolder(BaseHolder holder, int position) {
    MultiEntity entity = getItem(position);
    if (getCustomViewType(position) == VIEW_TEXT) {
        MultiText text = (MultiText) entity;
        TextHolder textHolder = (TextHolder) holder;
        textHolder.textView.setText(text.getContent());
    } else {
        MultiImage image = (MultiImage) entity;
        ImageHolder imageHolder = (ImageHolder) holder;
        imageHolder.imageView.setImageResource(image.getResId());
    }
}

Exception相关问题

1.更新列表时报异常 java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling

这个异常是在我写一个备份手机安装包的APP是遇到的,Item中带有 CheckBox控件,选中的Item会备份。但是点击的同时稍微碰一下列表就会报此异常。

appAdapter.setViewClickListener(new AppAdapter.OnViewClickListener() {
    @Override
    public void onCheckedChange(int position, boolean isChecked) {
        AppItem appItem = appAdapter.getItem(position);
        appItem.isCheck = isChecked;
        appAdapter.updateItem(appItem);
    }
});

updateItem()方法如下:

public void updateItem(M data) {
    int index = this.dataList.indexOf(data);
    if(index >= 0) {
        this.dataList.set(index, data);
        if(this.headerView == null) {
            this.notifyItemChanged(index);
        } else {
            this.notifyItemChanged(index + 1);
        }

    }
}

异常意思为:RecyclerView计算布局或者滚动时调用了不合状态的方法 notifyItemChanged(int)

StackOverFlow上找到了类似的问题和解释:

onBindViewHolder() is not a method that initialize ViewHolder. This method is step of refresh each recycler item. When you call notifyDataSetChanged(), onBindViewHolder() will be called as the number of each item times.

So If you notifyDataSetChanged() put into onCheckChanged() and initialize checkBox in onBindViewHolder(), you will get IllegalStateException because of circular method call.

click checkbox -> onCheckedChanged() -> notifyDataSetChanged() -> onBindViewHolder() -> set checkbox -> onChecked...

解决办法有两种:

1.采用StackOverFlow的方法,添加flag。

private boolean onBind;

public ViewHolder(View itemView) {
    super(itemView);
    mCheckBox = (CheckBox) itemView.findViewById(R.id.checkboxId);
    mCheckBox.setOnCheckChangeListener(this);
}

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    if(!onBind) {
        // your process when checkBox changed
        // ...

        notifyDataSetChanged();
    }
}

...

@Override
public void onBindViewHolder(YourAdapter.ViewHolder viewHolder, int position) {
    // process other views 
    // ...

    onBind = true;
    viewHolder.mCheckBox.setChecked(trueOrFalse);
    onBind = false;
}

2.在RecyclerView停止计算布局并且不滚动是更新数据

appAdapter.setViewClickListener(new AppAdapter.OnViewClickListener() {
    @Override
    public void onCheckedChange(int position, boolean isChecked) {
        if (appListRv.getScrollState() == RecyclerView.SCROLL_STATE_IDLE
                && !appListRv.isComputingLayout()) {
            AppItem appItem = appAdapter.getItem(position);
            appItem.isCheck = isChecked;
            appAdapter.updateItem(appItem);
        }
    }
});
0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区