Android导航错误:java.lang.IllegalArgumentException:导航目标com.example ---此NavController未知

时间:2019-10-19 19:40:07

标签: android android-studio android-fragments android-architecture-components android-architecture-navigation

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

注意:当您不导航到RegisterFragment

时不会发生该错误

LoginFragment:

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$3.onChanged(LoginFragment.kt:71)
    at com.example.---.ui.login.LoginFragment$onCreateView$3.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$1.invoke(LoginViewModel.kt:15)
    at com.example.---.viewModel.LoginViewModel$firebaseUserAuth$1.invoke(LoginViewModel.kt:12)
    at com.example.---.data.FirebaseUserAuth$login$1.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)

2 个答案:

答案 0 :(得分:1)

您在viewModel.loginAuthData.observe(this, Observer {})中使用onCreateView(),即使用Fragment(通过this)作为LifecycleOwner进行观察。这总是错误的-从viewLifecycleOwner进行观察时,您应该使用onCreateView()

viewModel.loginAuthData.observe(viewLifecycleOwner, Observer {
   ...
})

LiveData的工作方式是继续保持注册状态,直到给定的LifecycleOwner被销毁为止。当您传递this时,它等待Fragment本身被销毁。但是,片段在后堆栈上不会被销毁(仅销毁了它们的视图,因此销毁了它们的viewLifecycleOwner)。这意味着原始 LiveData永远不会注销其观察者。

这意味着onCreateView()第二次发生时(即,您按下后退按钮并重新创建视图),将创建并注册一个 second 观察者。现在,您有两个观察程序同时运行。当它们都运行时,第一个成功运行并调用navigate()。当第二个运行时,NavController已移至下一个目标,因此不再找到在前一个目标上注册的任何操作,从而给您IllegalArgumentException

使用viewLifecycleOwner,当Fragment的视图被销毁时,原始LiveData被正确销毁。这意味着当您回击并再次调用onCreateView时,一次只有一个观察者处于活动状态,您不会遇到此问题。

答案 1 :(得分:0)

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

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