Android:getChildDrawingOrder() 返回无效索引 1(子项计数为 1)

问题描述 投票:0回答:2

这是堆栈跟踪:

Fatal Exception: java.lang.IndexOutOfBoundsException: getChildDrawingOrder() returned invalid index 1 (child count is 1)
   at android.view.ViewGroup.getAndVerifyPreorderedIndex(ViewGroup.java:1988)
   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4204)
   at android.view.View.draw(View.java:20373)
   at android.view.View.updateDisplayListIfDirty(View.java:19315)
   at android.view.View.draw(View.java:20093)
   at android.view.ViewGroup.drawChild(ViewGroup.java:4421)
   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207)
   at android.view.View.updateDisplayListIfDirty(View.java:19306)
   at android.view.View.draw(View.java:20093)
   at android.view.ViewGroup.drawChild(ViewGroup.java:4421)
   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207)
   at android.view.View.updateDisplayListIfDirty(View.java:19306)
   at android.view.View.draw(View.java:20093)
   at android.view.ViewGroup.drawChild(ViewGroup.java:4421)
   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4231)
   at android.view.View.draw(View.java:20373)
   at androidx.viewpager.widget.ViewPager.draw(ViewPager.java:2426)
   at android.view.View.updateDisplayListIfDirty(View.java:19315)
   at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
   at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
   at android.view.View.updateDisplayListIfDirty(View.java:19274)
   at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
   at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
   at android.view.View.updateDisplayListIfDirty(View.java:19274)
   at android.view.View.draw(View.java:20093)
   at android.view.ViewGroup.drawChild(ViewGroup.java:4421)
   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4231)
   at android.view.View.updateDisplayListIfDirty(View.java:19306)
   at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
   at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
   at android.view.View.updateDisplayListIfDirty(View.java:19274)
   at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
   at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
   at android.view.View.updateDisplayListIfDirty(View.java:19274)
   at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
   at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
   at android.view.View.updateDisplayListIfDirty(View.java:19274)
   at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
   at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
   at android.view.View.updateDisplayListIfDirty(View.java:19274)
   at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
   at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
   at android.view.View.updateDisplayListIfDirty(View.java:19274)
   at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
   at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
   at android.view.View.updateDisplayListIfDirty(View.java:19274)
   at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:686)
   at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:692)
   at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:800)
   at android.view.ViewRootImpl.draw(ViewRootImpl.java:3496)
   at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3283)
   at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2818)
   at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1780)
   at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7827)
   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
   at android.view.Choreographer.doCallbacks(Choreographer.java:723)
   at android.view.Choreographer.doFrame(Choreographer.java:658)
   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
   at android.os.Handler.handleCallback(Handler.java:789)
   at android.os.Handler.dispatchMessage(Handler.java:98)
   at android.os.Looper.loop(Looper.java:164)
   at android.app.ActivityThread.main(ActivityThread.java:6944)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

我似乎不知道如何追溯到问题所在。这似乎是某个地方有 ViewGroup 的东西。 我回顾了代码差异,但我无法确切地弄清楚哪一个会导致这种情况,因为没有人操纵他们的孩子。想知道之前是否有人遇到过这个非常模糊的错误跟踪。

android indexoutofboundsexception viewgroup
2个回答
1
投票

我还收到了这个堆栈跟踪,但没有明确的回溯到我的代码。

问题在于,以编程方式添加或删除 ViewGroup 上的视图以及绘制 ViewGroup 时,存在某种竞争条件。

为了解决问题或帮助诊断问题,请在代码库中搜索对 ViewGroup#removeAllViews、ViewGroup#addView、ViewGroup#removeView 的 api 调用。正如其他用户在评论中指出的那样,仅通过堆栈跟踪很难帮助解决您的特定情况。您介意更新帖子以显示应用程序的某些部分,您可以在其中调用以下内容来帮助诊断/解决您的特定问题吗?

ViewGroup.removeAllViews()
ViewGroup.addView(...)
ViewGroup.removeView(...)

帮助我的应用程序避免此类崩溃的修复方法是更改这些调用以切换 ViewGroup 内视图的可见性,而不是添加/删除视图本身。即膨胀并添加一次视图,然后从那里切换可见性。

我的错误代码使用removeAllViews和addView的示例:

    val materialButtonToggleGroup : MaterialButtonToggleGroup = binding.startRideFragmentToggle
    if (materialButtonToggleGroup.childCount != fareInfo.size) {
        materialButtonToggleGroup.removeAllViews()
        for (rideService in fareInfo) {
            val textView = LayoutInflater.from(requireContext())
                .inflate(R.layout.material_button_outlined, materialButtonToggleGroup, false) as Button
            materialButtonToggleGroup.addView(textView)
        }
    }

解决问题的代码(我们从不删除视图,如果视图太多,只需将可见性设置为 View.GONE ):

    val materialButtonToggleGroup : MaterialButtonToggleGroup = binding.startRideFragmentToggle
    fareInfo.forEachIndexed { index, rideService ->
        if (index >= materialButtonToggleGroup.childCount) {
            val textView = LayoutInflater.from(requireContext())
                .inflate(
                    R.layout.material_button_outlined,
                    materialButtonToggleGroup,
                    false
                ) as Button
            materialButtonToggleGroup.addView(textView)
        }
    }

    for (i in 0 until materialButtonToggleGroup.childCount) {
        val toggleTabText = materialButtonToggleGroup.getChildAt(i)
        if (i < fareInfo.size) {
            toggleTabText.visibility = View.VISIBLE
        } else {
            toggleTabText.visibility = View.GONE
        }
    }

0
投票

我与 Fulguris 也有类似的 问题。正如这个answer中所指出的,它似乎与渲染期间视图层次结构的操作有关。正如他们的文档所暗示的,诸如

addView
removeView
之类的函数不应该从渲染上下文中调用。然而,这到底意味着什么还没有明确定义。就我而言,我是从
AnimatorListener.onAnimationEnd
给他们打电话的,虽然它似乎在大多数设备上大部分时间都能工作,但偶尔会导致
IndexOutOfBoundsException

我的解决方案是使用

View.post
中的
onAnimationEnd
来执行此类操作。

© www.soinside.com 2019 - 2024. All rights reserved.