Android Handler解决RecyclerView notifyDataSetChanged();问题

当RecyclerView 正在刷新的时候,notifyDataSetChanged()会报一个bug

Cannot call this method while RecyclerView is computing a layout or scrolling

出现这个问题原因:

在RecyclerView中,当RecyclerView的Adapter更新数据时,按照流程会执行assertNotInLayoutOrScroll()这个方法。
assertNotInLayoutOrScroll()这个方法从方法名即可看出,用来检测是否正在layout或者scroll。

void assertInLayoutOrScroll(String message) {
        if (!isComputingLayout()) {
            if (message == null) {
                throw new IllegalStateException("Cannot call this method unless RecyclerView is "
                        + "computing a layout or scrolling");
            }
            throw new IllegalStateException(message);
        }
    }

在其中,是通过isComputingLayout()判断

public boolean isComputingLayout() {
        return mLayoutOrScrollCounter > 0;
    }

而mLayoutOrScrollCounter这个变量或者说是标志位会在开始绘制的时候mLayoutOrScrollCounter++;在退出绘制的时候mLayoutOrScrollCounter–;
而从log中看,我的方法onItemClear()正好在绘制流程之中,也就是此时的mLayoutOrScrollCounter是非0的。故而在onItemClear()中直接调用notifyDataSetChanged()方法会CRASH。

解决办法:

// 你需要确保这个Handler的Looper是主线程的Looper
// 也就是说,如果下列code块是在主线程中执行,请忽略。
// 如果不是,则需要你 Handler handler = new Handler(Looper.getMainLooper());
Handler handler = new Handler();
handler.post(new Runnable() {
    @Override
    public void run() {
        notifyDataSetChanged();
    }
});

解决原理:
Android中的UI的刷新其实是通过消息机制实现的。通过对消息的分发,从而进行不同处理。

06-27 16:49:50.464 E/AndroidRuntime(20889):     at android.os.Handler.handleCallback(Handler.java:836)
06-27 16:49:50.464 E/AndroidRuntime(20889):     at android.os.Handler.dispatchMessage(Handler.java:103)
06-27 16:49:50.464 E/AndroidRuntime(20889):     at android.os.Looper.loop(Looper.java:203)

通过Handler.post方法将一个Runnable方法块放入MessageQueue[先进先出,后进后出]中去等待执行。而主线程的Looper则会在循环取此队列中的消息。一般情况下,这个流程是串行的。所以当使用Handle.post的时候,UI的更新消息会先被消化掉,等被post的消息被Looper从MessageQueue中取出的时候,【数据源更新】的操作才会被执行。但是此时RecyclerView的绘制已经完成,mLayoutOrScrollCounter也已经被置为0,故而能够成功更新数据源

转载:RecycleView刷新bug

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值