Android之提示Cannot call this method while RecyclerView is computing a layout or scrolling

1 问题

java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling androidx.recyclerview.widget.RecyclerView{24d6f3b VFED.V... ......ID 0,657-1074,1911 #7f090143 app:id/recyclerView}, adapter:com.appsinnova.android.keepshare.widget.PopupLanguage$LanguageListAdapter@57e8658, layout:androidx.recyclerview.widget.LinearLayoutManager@3de33b1, context:com.appsinnova.android.keepshare.account.SettingActivity@4b834ad
        at androidx.recyclerview.widget.RecyclerView.assertNotInLayoutOrScroll(RecyclerView.java:3051)
        at androidx.recyclerview.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:5536)
        at androidx.recyclerview.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:12253)
        at androidx.recyclerview.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:7354)
        at com.appsinnova.android.keepshare.widget.PopupLanguage$LanguageListAdapter$convert$1.onCheckedChanged(PopupLanguage.kt:108)
        at android.widget.CompoundButton.setChecked(CompoundButton.java:171)
        at com.appsinnova.android.keepshare.widget.PopupLanguage$LanguageListAdapter.convert(PopupLanguage.kt:104)
        at com.appsinnova.android.keepshare.widget.PopupLanguage$LanguageListAdapter.convert(PopupLanguage.kt:98)
        at com.chad.library.adapter.base.BaseQuickAdapter.onBindViewHolder(BaseQuickAdapter.java:937)
        at com.chad.library.adapter.base.BaseQuickAdapter.onBindViewHolder(BaseQuickAdapter.java:66)
        at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
        at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
        at android.view.View.layout(View.java:21112)
        at android.view.ViewGroup.layout(ViewGroup.java:6400)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1828)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
        at android.view.View.layout(View.java:21112)

出现问题的代码地方

            helper.getView<CheckBox>(R.id.selecte_state).setOnCheckedChangeListener { buttonView, isChecked ->
                if (isChecked) {
					adapter.notifyDataSetChanged()
                }
            }

在checkbox里面设置了状态监听,然后调用了notifyDataSetChanged()出现的

错误日志第一行的方法

assertNotInLayoutOrScroll

我们看下源码

    /**
     * Checks if RecyclerView is in the middle of a layout or scroll and throws an
     * {@link IllegalStateException} if it <b>is</b>.
     *
     * @param message The message for the exception. Can be null.
     * @see #assertInLayoutOrScroll(String)
     */
    void assertNotInLayoutOrScroll(String message) {
        if (isComputingLayout()) {
            if (message == null) {
                throw new IllegalStateException("Cannot call this method while RecyclerView is "
                        + "computing a layout or scrolling" + exceptionLabel());
            }
            throw new IllegalStateException(message);
        }
        if (mDispatchScrollCounter > 0) {
            Log.w(TAG, "Cannot call this method in a scroll callback. Scroll callbacks might"
                            + "be run during a measure & layout pass where you cannot change the"
                            + "RecyclerView data. Any method call that might change the structure"
                            + "of the RecyclerView or the adapter contents should be postponed to"
                            + "the next frame.",
                    new IllegalStateException("" + exceptionLabel()));
        }
    }

我们发现isComputingLayout()这个函数true就抛出这个异常,所以看下这个函数实现

我们可以看到recycleView被lockdown了,我们怎么解决呢?上面也说了,等view加载好或者用handler

处理

2 解决办法

方法1、

            helper.getView<CheckBox>(R.id.selecte_state).setOnCheckedChangeListener { buttonView, isChecked ->
                if (isChecked) {
                     Handler().post(Runnable {
                        selectedIndex = position
                        listener(helper.itemView, item!!.languageIndex)
                    })
                }
            }

方法2、

            helper.getView<CheckBox>(R.id.selecte_state).setOnCheckedChangeListener { buttonView, isChecked ->
                if (isChecked) {
                    recycleView.post(Runnable {
                        selectedIndex = position
                        listener(helper.itemView, item!!.languageIndex)
                    })
                }
            }
发布了1083 篇原创文章 · 获赞 693 · 访问量 310万+

猜你喜欢

转载自blog.csdn.net/u011068702/article/details/105301458