【问题标题】:How to hard throw IndexOutOfBoundsException for RecyclerView?如何为 RecyclerView 硬抛出 IndexOutOfBoundsException?
【发布时间】:2017-11-13 11:57:56
【问题描述】:

我有很小的机会(如果信任fabric crashreport,当天有0.5% 的用户)在RecyclerView 的两种方法中捕获IndexOutOfBoundsException: Inconsistency detected(我在fabric 中看到了崩溃日志):

  • validateViewHolderForOffsetPosition()
  • 尝试GetViewHolderForPositionByDeadline()

我在其他情况下搜索了相同的问题,我意识到从不同线程检索和更新适配器中的数据时可能会出现此问题。我傻乎乎地解决了这个问题,但理论上这可以正常工作:

    private fun setUpdates() {
                //...

                //fix code start
                if (Looper.getMainLooper().thread == Thread.currentThread()) {
                    log("thread is main")
                    adapter.notifyDataSetChanged()
                } else {
                    log("thread NOT is main")
                    notifyOnUi()
                }
                //fix code end

                //...
            }

    private fun notifyOnUi() {
        Handler(Looper.getMainLooper()).post {
            log("notify data set changes on UI")
            adapter.notifyDataSetChanged()
        }
    }

而且我不知道抛出此异常时如何重现情况。我尝试了多个线程的不同选项,在adapter.notifyDataSetChanges() 之前/之后/期间修改列表,但这个问题不会重现(没有修复代码)。

还有一个问题——我们能做些什么来为RecyclerView 中的两个方法抛出IndexOutOfBoundsException: Inconsistency detected. ... 进行测试——是否修复我的代码这个问题?:

  • validateViewHolderForOffsetPosition()
  • 尝试GetViewHolderForPositionByDeadline()

【问题讨论】:

    标签: android android-recyclerview android-adapter


    【解决方案1】:

    首先,调用适配器的getItemCount()onCreateViewHolderonBindViewHolder等方法的是UI线程

    所以,如果不同的线程修改了这些方法使用的data,就会出现inconsistency。因为,通知中的数据不是最新的(notifyDataSetChanged 等...)。

    为了没有任何不一致,您必须修改数据并在主线程上发布的同一message中调用notifyDataSetChanged

    类似:

    private fun setUpdates(newData: Collection<Data>) {
        Handler(Looper.getMainLooper()).post {
            myData = newData // or whatever
            adapter.notifyDataSetChanged() // and notify within the same message
        }
    }
    

    【讨论】:

    • 我理解你)但我不知道reproduce 我的代码中的这个问题如何。我尝试创建许多线程并修改数据 - 我没有抛出这个异常。
    • 这是一个竞争条件...很难重现。但我遇到了同样的问题,更改我的代码以使用 UI 线程,看到问题从 Crashlytics 中消失!
    猜你喜欢
    • 2021-12-20
    • 2023-03-28
    • 1970-01-01
    • 2015-06-16
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    • 2018-06-17
    • 2013-02-07
    相关资源
    最近更新 更多