我收到一个错误: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)
答案 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