Android BottomNavigationView 每次使用导航组件重新创建片段

Posted

技术标签:

【中文标题】Android BottomNavigationView 每次使用导航组件重新创建片段【英文标题】:Android BottomNavigationView recreating Fragments each time with Navigation Component 【发布时间】:2021-12-27 00:07:07 【问题描述】:

我正在使用 BottomNavigationView 在 Home 和 Meetings 片段之间切换。每次我在它们之间切换时,都会重新创建每个 Fragment。我在它们之间使用 SharedViewModel 作为共享的“meetingID”变量,但它与片段一起被破坏和重新创建(更严重的是)。我正在使用 Jetpack 导航组件;我几乎完全复制了谷歌示例here。但是,它仍然无法正常工作。

看看我的 onCreate 和 onSupportNavigateUp:

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val navHostFragment = supportFragmentManager
            .findFragmentById(R.id.nav_host_fragment)
                as NavHostFragment

        navController = navHostFragment.navController
        setSupportActionBar(binding.toolBar)

        appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.homeFragment, R.id.meetingFragment
            )
        )

        setupActionBarWithNavController(navController, appBarConfiguration)

        binding.apply 
            navController.addOnDestinationChangedListener  _, destination, _ ->
                if (destination.id == R.id.loginFragment
                    || destination.id == R.id.registerFragment
                ) 
                    bottomNavigation.visibility = View.GONE
                 else 
                    bottomNavigation.visibility = View.VISIBLE
                
            

            bottomNavigation.setupWithNavController(navController)
        
    

    override fun onSupportNavigateUp(): Boolean 
        return navController.navigateUp(appBarConfiguration)
    

我的 nav_graph 相当丑:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/loginFragment">
    <fragment
        android:id="@+id/loginFragment"
        android:name="edu.fsu.equidistant.fragments.LoginFragment"
        android:label="fragment_login"
        tools:layout="@layout/fragment_login">
        <action
            android:id="@+id/action_loginFragment_to_homeFragment"
            app:destination="@id/homeFragment"
            app:launchSingleTop="true"
            app:popUpTo="@+id/nav_graph"
            app:popUpToInclusive="true" />
        <action
            android:id="@+id/action_loginFragment_to_registerFragment"
            app:destination="@id/registerFragment" />
    </fragment>
    <fragment
        android:id="@+id/registerFragment"
        android:name="edu.fsu.equidistant.fragments.RegisterFragment"
        android:label="fragment_register"
        tools:layout="@layout/fragment_register">
        <action
            android:id="@+id/action_registerFragment_to_homeFragment"
            app:destination="@id/homeFragment"
            app:launchSingleTop="true"
            app:popUpTo="@+id/nav_graph"
            app:popUpToInclusive="true" />
        <action
            android:id="@+id/action_registerFragment_to_loginFragment"
            app:destination="@id/loginFragment" />
    </fragment>
    <fragment
        android:id="@+id/homeFragment"
        android:name="edu.fsu.equidistant.fragments.HomeFragment"
        android:label="Home"
        tools:layout="@layout/fragment_home" >
        <argument
            android:name="email"
            app:argType="string" >
        </argument>

        <argument
            android:name="userId" >
        </argument>
        <action
            android:id="@+id/action_homeFragment_to_loginFragment"
            app:destination="@id/loginFragment" />
        <action
            android:id="@+id/action_homeFragment_to_profileFragment"
            app:destination="@id/profileFragment"
            app:enterAnim="@anim/nav_default_enter_anim"
            app:exitAnim="@anim/nav_default_enter_anim" />
    </fragment>
    <fragment
        android:id="@+id/profileFragment"
        android:name="edu.fsu.equidistant.fragments.ProfileFragment"
        android:label="fragment_profile"
        tools:layout="@layout/fragment_profile" >
        <argument
            android:name="userId" >
        </argument>
        <action
            android:id="@+id/action_profileFragment_to_loginFragment"
            app:destination="@id/loginFragment" />
        <action
            android:id="@+id/action_profileFragment_to_homeFragment"
            app:destination="@id/homeFragment"
            app:enterAnim="@anim/nav_default_enter_anim"
            app:exitAnim="@anim/nav_default_exit_anim"
            app:popEnterAnim="@anim/nav_default_pop_enter_anim"
            app:popExitAnim="@anim/nav_default_pop_exit_anim" />
    </fragment>
    <fragment
        android:id="@+id/meetingFragment"
        android:name="edu.fsu.equidistant.fragments.MeetingFragment"
        android:label="Meeting"
        tools:layout="@layout/fragment_meeting" />
</navigation>

我使用 appBarConfiguration 将每个 Fragment 设置为***,但没有。 . .有什么建议吗?

【问题讨论】:

您使用的是什么版本的导航? @ianhanniballake 当前稳定版本,2.3.5。感谢您提醒我应该提到这一点。 我已经尝试过最新的 beta 版本 2.4.0-beta02,但也存在同样的问题。 您是否阅读过Principles of Navigation,其中明确指出登录永远不应该是您的起始目的地,而Conditional Navigation guide 具体涵盖了您应该如何有条件地从您的实际起始目的地重定向登录(您的@ 987654326@)? @ianhanniballake 不幸的是,我没有。也许我会看看。你认为这可能是我烦恼的根源吗? 【参考方案1】:

@ianhanniballake 的想法是对的!

我愚蠢地使用 LoginFragment 作为我的目的地来笨拙地执行一些条件逻辑。快速重构,并将 HomeFragment 设置为实际的主目的地,它现在可以工作了。谢谢,@ianhanniballake。

【讨论】:

以上是关于Android BottomNavigationView 每次使用导航组件重新创建片段的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )

android 21 是啥版本

Android逆向-Android基础逆向(2-2)

【Android笔记】android Toast

图解Android - Android核心机制

Android游戏开发大全的目录