从 Activity 导航到 Fragment 并返回到 Activity 导致 activity 被创建多次

Navigation to Fragment from Activity and back to the Activity is causing the activity to be created multiple times

我遇到的问题好像很奇怪

文字

我有一个带有底部导航菜单的应用程序,其中有 3 个按钮,每个按钮有 3 个片段和一个 MainActivity。当导航到任何这些片段时,一切都按预期工作。 当我从这 3 个片段中的任何一个导航到另一个片段(我们称之为片段 4 或 fr4)时,问题就出现了。 假设我在 fr1,我有一个按钮可以将我带到 fr4。当我返回 fr1(使用 android 后退按钮或按下 fr1 的底部栏按钮)时,我在主要 activity 或 3 个片段中的任何一个中所做的每件事都会重复 2次。如果我再去 fr4,然后回到 fr1,那么一切都重复 3 次,依此类推。

在下面的代码中,fr1 是 fragment_home,fr4 是 fragment_profile。

代码

MainActivity.kt

class MainActivity : AppCompatActivity() {
    private lateinit var navView: BottomNavigationView
    private lateinit var binding: ActivityMainBinding

    private val sharedViewModel: SharedViewModel by viewModels()

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

        navView = binding.navView
        val navController = findNavController(R.id.nav_host_fragment_activity_main)
        navView.setupWithNavController(navController)
    }
    override fun onStart() {
        super.onStart()
        Timber.i("onStart main activity")
    }

    override fun onStop() {
        super.onStop()
        Timber.i("onStop main activity")
    }
}

framgnet1.kt

class HomeFragment : Fragment() {
    private var _binding: FragmentHomeBinding? = null
    private val binding get() = _binding!!
    private val sharedViewModel: SharedViewModel by activityViewModels()
    private val homeViewModel: HomeViewModel by viewModels()

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

        _binding = FragmentHomeBinding.inflate(inflater, container, false)
        val root: View = binding.root

        binding.lifecycleOwner = viewLifecycleOwner
        binding.sharedViewModel = sharedViewModel
        binding.homeViewModel = homeViewModel


        binding.historyButton.setOnClickListener{
             Timber.i("profile button clicked")
        }

        binding.profileButton.setOnClickListener { view ->
            profileButtonClicked(view)
        }

        return root
    }


    fun profileButtonClicked() {
        Timber.i("profile button clicked")
        val action = HomeFragmentDirections.homeToProfileAction()
        NavHostFragment.findNavController(this).navigate(action)
    }

}

mobile_navigation.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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mobile_navigation"
    app:startDestination="@+id/navigation_home">

    <fragment
        android:id="@+id/navigation_home"
        android:name="com.comp.comp.ui.home.HomeFragment"
        android:label="@string/title_home"
        tools:layout="@layout/fragment_home">
        <action
            android:id="@+id/home_to_profile_action"
            app:destination="@id/fragment_profile"
            app:launchSingleTop="true" />
    </fragment>

    <fragment
        android:id="@+id/navigation_dashboard"
        android:name="com.comp.comp.ui.dashboard.DashboardFragment"
        android:label="@string/title_dashboard"
        tools:layout="@layout/fragment_dashboard" >
    </fragment>

    <fragment
        android:id="@+id/navigation_notifications"
        android:name="com.comp.comp.ui.notifications.NotificationsFragment"
        android:label="@string/title_notifications"
        tools:layout="@layout/fragment_notifications" />
    <fragment
        android:id="@+id/fragment_profile"
        android:name="com.comp.comp.fragment_profile"
        android:label="fragment_profile"
        tools:layout="@layout/fragment_profile" />

</navigation>

我尝试在导航操作上切换 launchSingleTop="true",但无济于事。

发生以下情况:

  1. 在主页片段中,如果我按下历史记录按钮,它会打印一次“配置文件按钮已单击”
  2. 如果我随后点击个人资料按钮,应用会导航到个人资料片段
  3. 我使用后退按钮或按底部栏上的主页按钮返回主页片段
  4. 如果我现在按下历史记录按钮,“profile button clicked”会打印两次。

如果我重复上述步骤,那么下次我按历史记录按钮时,它将打印“配置文件按钮已单击”3 次,依此类推。

我也测试过去另一个activity,我的activity运行s中的onStop()方法也是我去过的两倍个人资料页面曾经。当我回到主 activity 和 onStart() 方法 运行 两次时也是如此。我所做的每件事都会 运行 2 次(或更多),具体取决于我访问个人资料页面的次数。每次我访问同时处于活动状态的个人资料页面时,它似乎都创建了一个主要 activity。有什么想法吗?

我尝试了所有方法都无济于事。然后我意识到,在每次配置更改时,它都会种植一个新的 Jake Wharton 的 Timber 调试树,并且它会记录所有树的所有信息。 希望这可以帮助某人。我的错误是木材​​刨削在 MainActivity 的 onCreate 中,而它应该在应用程序的 OnCreate 中。