Android Navigation Error: java.lang.IllegalArgumentException: navigation destination com.example--- is unknown to this NavController

Android Navigation Error: java.lang.IllegalArgumentException: navigation destination com.example--- is unknown to this NavController

我收到一个错误:java.lang.IllegalArgumentException,只有当我从 LoginFragment 导航到 RegisterFragment 然后按返回按钮转到上一个片段时才会发生错误(LoginFragment) 并输入电子邮件和密码,然后按登录按钮。当我注释行 view!!.findNavController().navigate(LoginFragmentDirections.actionLoginFragmentToHomeContainerFragment()) 时,错误没有发生,但我必须导航到 HomeFragment。如何解决?

注意: 当您不导航到 RegisterFragment

时,不会发生错误

登录片段:

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
{
    val binding: FragmentLoginBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_login, container, false)

    val login = binding.loginBtn
    val emailField = binding.inputEmail
    val passwordField = binding.inputPassword
    val signUp = binding.loginSignup

    binding.viewModel = viewModel
    binding.lifecycleOwner = this

    signUp.setOnClickListener {
        view!!.findNavController().navigate(LoginFragmentDirections.actionLoginFragmentToRegisterFragment())
    }

    login.setOnClickListener {
        val email = emailField.text.toString().trim()
        val password = passwordField.text.toString().trim()

        if(email.isEmpty())
        {
            .................
        }

        if(!Patterns.EMAIL_ADDRESS.matcher(email).matches())
        {
            .................
        }

        viewModel.userLogin(email,password)
    }

    viewModel.loginAuthData.observe(this, Observer { userAuthData ->
        if(userAuthData.checkAuth != null)
        {
            if(userAuthData.checkAuth!!)
            {
                Snackbar.make(activity!!.findViewById(android.R.id.content), "Auth Pass", Snackbar.LENGTH_SHORT).show()
                //The error doesn't occur if i comment this line >>
                view!!.findNavController().navigate(LoginFragmentDirections.actionLoginFragmentToHomeContainerFragment())
            }
            else
            {
                Snackbar.make(activity!!.findViewById(android.R.id.content), "Auth Fail", Snackbar.LENGTH_SHORT).show()
            }
        }
    })

    return binding.root
}

错误:

  Process: com.example.---, PID: 24721
  java.lang.IllegalArgumentException: navigation destination com.example.---:id/action_loginFragment_to_homeContainerFragment is unknown to this NavController
    at androidx.navigation.NavController.navigate(NavController.java:789)
    at androidx.navigation.NavController.navigate(NavController.java:730)
    at androidx.navigation.NavController.navigate(NavController.java:716)
    at androidx.navigation.NavController.navigate(NavController.java:907)
    at com.example.---.ui.login.LoginFragment$onCreateView.onChanged(LoginFragment.kt:71)
    at com.example.---.ui.login.LoginFragment$onCreateView.onChanged(LoginFragment.kt:20)
    at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
    at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:149)
    at androidx.lifecycle.LiveData.setValue(LiveData.java:307)
    at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50)
    at com.example.---.viewModel.LoginViewModel.authCallBack(LoginViewModel.kt:37)
    at com.example.---.viewModel.LoginViewModel.access$authCallBack(LoginViewModel.kt:12)
    at com.example.---.viewModel.LoginViewModel$firebaseUserAuth.invoke(LoginViewModel.kt:15)
    at com.example.---.viewModel.LoginViewModel$firebaseUserAuth.invoke(LoginViewModel.kt:12)
    at com.example.---.data.FirebaseUserAuth$login.onComplete(FirebaseUserAuth.kt:27)
    at com.google.android.gms.tasks.zzj.run(Unknown Source)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6077)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

尝试获取包含 Activity Activity.findNavController(IdOfView) 的 NavController 而不是 view!!.findNavController()

有关导航的更多信息: https://developer.android.com/reference/kotlin/androidx/navigation/package-summary#findnavcontroller

您正在 onCreateView() 中使用 viewModel.loginAuthData.observe(this, Observer {}),即使用 Fragment(通过 this)作为您观察的 LifecycleOwner。这总是错误的——当从 onCreateView():

观察时,你应该改用 viewLifecycleOwner
viewModel.loginAuthData.observe(viewLifecycleOwner, Observer {
   ...
})

LiveData 的工作原理是它会继续保持注册状态,直到给定的 LifecycleOwner 被销毁。当你传递 this 时,它会等待 Fragment 本身被销毁。但是,碎片在返回堆栈时 不会 被销毁(只有它们的视图以及它们的 viewLifecycleOwner 被销毁)。这意味着 original LiveData 永远不会注销其观察者。

这意味着当 onCreateView() 第二次发生时(即,您点击后退按钮并重新创建视图),将创建并注册 second 观察者.您现在 两个 个观察者同时 运行ning。由于他们都 运行,第一个成功 运行 并调用 navigate()。当第二个 运行s 时,NavController 已经移动到下一个目的地,因此不再找到在前一个目的地注册的任何操作,给你一个 IllegalArgumentException.

通过使用viewLifecycleOwner,当片段的视图被销毁时,原始的 LiveData 被正确地销毁。这意味着当你回击并再次调用 onCreateView 时,一次只有一个观察者处于活动状态,你不会 运行 进入这个问题。