首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >导航主机导航时变为空(Android导航组件)

导航主机导航时变为空(Android导航组件)
EN

Stack Overflow用户
提问于 2019-06-14 17:42:54
回答 2查看 3.8K关注 0票数 3

我正在创建一个游戏,用户通过一系列的5个屏幕。在最后一个屏幕上,用户可以选择结束游戏,在这一点上,他们会被带回开始屏幕。当用户结束游戏,然后重新开始时,我的问题就出现了。在浏览应用程序时,无法找到导航主机片段。

第一次通过这个应用程序时,它在通常情况下导航,,但是第二次,导航主机就找不到了。

我尝试使用不同的视图来查找导航主机,在调试过程中,我发现对于无法找到的片段,父程序等于null。

这就是我在片段onViewCreated()中导航的地方。

代码语言:javascript
复制
    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)
                }
            })

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

代码语言:javascript
复制
     btn_end_game.setOnClickListener {
                viewModel.endGame()
                timer.cancel()
                Navigation.findNavController(view).navigate(R.id.action_gameFragment_to_startFragment)
            }

保存导航主机片段的MainActivity的布局是:

代码语言:javascript
复制
    <?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>

我确实意识到,我只是在后面堆栈的顶部添加,而我更愿意弹回第一个片段。我只是不知道片段是空的。

下面是nav_graph.xml

代码语言:javascript
复制
    <?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} does not have a NavController set

EN

回答 2

Stack Overflow用户

发布于 2019-06-17 01:50:51

LiveData记住当前数据,并将在观察者再次启动时自动重新传递数据,这使得它不适合触发导航操作的事件:每次启动片段时,都会触发对navigate()的操作,因此不可能真正弹回该片段。

请注意,在后台堆栈上没有销毁碎片。如果您要更改片段在后端堆栈上所依赖的底层数据,则应该使用viewLifecycleOwner而不是this (代表片段),因为在onViewCreated()中观察时传递给observe()的LifecycleOwner。这将确保一旦视图被销毁(即进入后台堆栈),就不会再得到观察者回调。

从片段中使用activity!! 作为LifecycleOwner是绝对错误的,因为这意味着即使碎片被完全销毁,观察者也不会被清理(只有在活动被销毁时才会清理)。

根据条件导航文档,推荐的方法是确保LiveData跟踪的是状态,而不是事件。这样,在调用navigate()之后,您可以更新状态,以确保当第二次回调发生时,不会再次调用navigate()。建议采用这种方法,而不是SingleLiveEvent方法

票数 2
EN

Stack Overflow用户

发布于 2020-01-06 04:57:03

就连我过去从当前片段导航到下一个片段时也面临着同样的问题,在硬件navHost的背面按下将为null,我所做的错误是,我已经将变量navController全局化了,我过去常常在onCreate()中像这样实例化。

在此之前:

代码语言:javascript
复制
class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        navController = this.findNavController(R.id.myNavHostFragment)
        NavigationUI.setupActionBarWithNavController(this,navController)
    }

    override fun onSupportNavigateUp(): Boolean {
        return navController.navigateUp()
    }
}

之后:

现在它在这个变化之后起作用了

代码语言:javascript
复制
class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        navController = this.findNavController(R.id.myNavHostFragment)
        NavigationUI.setupActionBarWithNavController(this,navController)
    }

    override fun onSupportNavigateUp(): Boolean {
        val navController = this.findNavController(R.id.myNavHostFragment)
        return navController.navigateUp()
    }
}

如果使navController成为全局的,为什么它是空的呢??

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56602954

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档