gpt4 book ai didi

android - 导航时 Navigation Host 变为 null(Android 导航组件)

转载 作者:行者123 更新时间:2023-11-29 23:05:34 24 4
gpt4 key购买 nike

我正在创建一个游戏,用户可以在其中浏览一系列 5 个屏幕。在最后一个屏幕上,用户可以选择结束游戏,此时他们将返回到开始屏幕。当用户结束游戏然后重新开始时,我的问题就来了。在应用程序中导航时,找不到导航主机 fragment 。

第一次通过app正常导航,第二次找不到导航主机。

我尝试过使用不同的 View 来查找导航宿主,并且在调试时,我看到对于找不到它的 fragment ,父级等于null。

这是我在 onViewCreated() fragment 中导航的地方

    viewModel.getGameUpdates().observe(activity!!, Observer { updatedGame ->
if(updatedGame.playerList.size == 0){
Log.d("END","END")
viewModel.endGame()
}
adapter?.players = updatedGame.playerList

if(updatedGame.started){
Navigation.findNavController(view).navigate(R.id.action_waitingFragment_to_gameFragment)
}
})

这是用户点击导航回到第一个屏幕的时刻:

     btn_end_game.setOnClickListener {
viewModel.endGame()
timer.cancel()
Navigation.findNavController(view).navigate(R.id.action_gameFragment_to_startFragment)
}

包含导航主机 fragment 的 MainActivity 的布局是:

    <?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">


<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />

</FrameLayout>

我确实意识到,当我宁愿弹出回到第一个 fragment 时,我只是在返回堆栈的顶部添加。我只是迷失了 fragment 如何为空。

下面是nav_graph.xml

    <?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph" app:startDestination="@id/startFragment">

<fragment android:id="@+id/startFragment" android:name="com.dangerfield.spyfall.start.StartFragment"
android:label="StartFragment">
<action android:id="@+id/action_startFragment_to_joinGameFragment" app:destination="@id/joinGameFragment"/>
<action android:id="@+id/action_startFragment_to_newGameFragment" app:destination="@id/newGameFragment"/>
</fragment>
<fragment android:id="@+id/newGameFragment" android:name="com.dangerfield.spyfall.newGame.NewGameFragment"
android:label="NewGameFragment">
<action android:id="@+id/action_newGameFragment_to_waitingFragment" app:destination="@id/waitingFragment"/>
</fragment>
<fragment android:id="@+id/joinGameFragment" android:name="com.dangerfield.spyfall.joinGame.JoinGameFragment"
android:label="JoinGameFragment">
<action android:id="@+id/action_joinGameFragment_to_waitingFragment" app:destination="@id/waitingFragment"/>
</fragment>
<fragment android:id="@+id/waitingFragment" android:name="com.dangerfield.spyfall.waiting.WaitingFragment"
android:label="WaitingFragment">
<action android:id="@+id/action_waitingFragment_to_gameFragment" app:destination="@id/gameFragment"/>
<action android:id="@+id/action_waitingFragment_to_startFragment" app:destination="@id/startFragment"/>
</fragment>
<fragment android:id="@+id/gameFragment" android:name="com.dangerfield.spyfall.game.GameFragment"
android:label="GameFragment">
<action android:id="@+id/action_gameFragment_to_startFragment" app:destination="@id/startFragment"/>
</fragment>
</navigation>

这是崩溃后给出的消息:java.lang.IllegalStateException: View android.widget.ScrollView{637e4ce VFED.V... ......ID 0,0-1440,2308} 没有设置 NavController/p>

最佳答案

LiveData 会记住当前数据,并会在观察者再次启动时自动重新传送它,使其不适用于触发导航操作的事件:您对 navigate() 的操作每次您的 fragment 启动时都会被触发,因此不可能真正弹回该 fragment 。

请注意, fragment 在 返回堆栈时不会被销毁。如果您在 Fragment 位于返回堆栈上时更改 Fragment 所依赖的基础数据,则应使用 viewLifecycleOwner 而不是 this(代表 Fragment)在 onViewCreated() 中观察时,您的 LifecycleOwner 传递给 observe()。这确保一旦您的 View 被销毁(即,您进入返回堆栈),您将不再获得观察者回调。

activity!! 在 Fragment 中用作 LifecycleOwner 绝对是错误的,因为这意味着即使 Fragment 完全关闭,观察者也不会被清理destroyed(它只会在 Activity 被销毁时被清理)。

根据 conditional navigation documentation ,推荐的方法是确保您的 LiveData 跟踪状态而不是事件。这样,在您调用 navigate() 之后,您可以更新状态以确保当回调发生第二次时,您不会再次调用 navigate()时间。建议在 SingleLiveEvent approach 上使用此方法.

关于android - 导航时 Navigation Host 变为 null(Android 导航组件),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56602954/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com