快速点击Android概览按钮两次时出现内部异常/崩溃

3

我有一个名为CustomArFragment(Sceneform 1.15的ArFragment子类)的片段,它包含在MainActivity中。在某个时刻,我通过使用新实例替换来重置片段。我通过在MainActivity中调用以下方法来执行此操作:

fun reset() {
        val oldFragment = (supportFragmentManager.findFragmentById(R.id.custom_ar_fragment)) as? CustomArFragment ?: return
        val newArFragment = CustomArFragment()

        val transaction = supportFragmentManager.beginTransaction()
        transaction.remove(oldFragment)
        transaction.add(R.id.custom_ar_fragment, newArFragment)
        transaction.commit()
}

现在,正如我所说的,替换一开始似乎可以正常工作,并且新片段在替换后像往常一样运行。然而,如果我在调用reset()之后的任何时候快速连续按两次android概览按钮,我会收到以下错误提示,这似乎与我无法跟踪的一些内部调用有关:
java.lang.NullPointerException: throw with null exception
        at com.google.ar.sceneform.utilities.Preconditions.checkNotNull(SourceFile:3)
        at com.google.ar.sceneform.SceneView.onLayout(SourceFile:41)
        at com.google.ar.sceneform.ArSceneView.onLayout(SourceFile:79)
        at android.view.View.layout(View.java:20729)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:20729)
        at android.view.ViewGroup.layout(ViewGroup.java:6198)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:20729)
        at android.view.ViewGroup.layout(ViewGroup.java:6198)
        at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1915)
        at android.view.View.layout(View.java:20729)
        at android.view.ViewGroup.layout(ViewGroup.java:6198)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:20729)
        at android.view.ViewGroup.layout(ViewGroup.java:6198)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
        at android.view.View.layout(View.java:20729)
        at android.view.ViewGroup.layout(ViewGroup.java:6198)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:20729)
        at android.view.ViewGroup.layout(ViewGroup.java:6198)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
        at android.view.View.layout(View.java:20729)
        at android.view.ViewGroup.layout(ViewGroup.java:6198)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:757)
        at android.view.View.layout(View.java:20729)
        at android.view.ViewGroup.layout(ViewGroup.java:6198)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2859)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2386)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1524)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7398)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1092)
        at android.view.Choreographer.doCallbacks(Choreographer.java:888)
        at android.view.Choreographer.doFrame(Choreographer.java:819)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1078)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:201)
        at android.app.ActivityThread.main(ActivityThread.java:6815)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)

现在,我不确定这是否与Sceneform相关的错误,还是我替换片段的方式有问题。

我想澄清一下,除非我在替换完成后双击应用程序概述按钮,否则替换工作得非常完美,并且我没有在CustomArFragment的生命周期方法中执行任何可能干扰替换的操作。因此,如果我按概述按钮,然后等待一两秒钟再次按下它以打开应用程序,则所有内容都按预期工作而不会崩溃。

非常感谢您的帮助,我已经无法想出可能引起此问题的原因!

1个回答

0

崩溃似乎与某些ARCore/Sceneform资源在删除旧片段后仍保持运行一段时间有关,但仍然引用已删除的片段(我解决这个问题已经有一段时间了,所以我不记得确切的原因,但我认为是这个原因)。

无论如何,为了避免崩溃,我发现唯一有效的方法是将已删除的片段添加到返回堆栈中。这样,sceneform/ARCore就不会遇到空指针。

    val oldFragment = (supportFragmentManager.findFragmentById(R.id.custom_ar_fragment)) as? CustomArFragment ?: return
    oldFragment.arSceneView.pause()
    val newArFragment = CustomArFragment()

    val transaction = supportFragmentManager.beginTransaction().remove(oldFragment).add(R.id.sceneform_fragment, newArFragment).addToBackStack(null)
    transaction.commit()
    supportFragmentManager.executePendingTransactions()

当然,将旧片段保存到后退栈中并不理想,因为我从未打算返回它们。但是,由于我假设片段的重置次数很少,所以这对我来说已经足够好了。但是,如果您找到了更好的重置ArFragment的解决方案,请告诉我。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接