带有协同程序的Android MVVM Jetpack导航组件

带有协同程序的Android MVVM Jetpack导航组件,android,android-jetpack-navigation,Android,Android Jetpack Navigation,我正在尝试实现android jetpack导航组件。 该案例与官方文件中的情况几乎相同: 但我的情况是,如果用户尚未登录,登录访问将记录在数据库(房间)中, 然后系统将强制用户登录。 我过去经常申报 登录片段的目标 然后依次定义如下 家庭碎片是开始的目标 如果在数据库中未找到用户数据,则显示登录页面 如果登录成功,请将用户带回主页并将登录数据保存到数据库 我使用MVVM体系结构和协同程序来运行REST请求 使用改装 以下是我使用的一些代码: 导航(xml) 家庭碎片 class Home

我正在尝试实现android jetpack导航组件。 该案例与官方文件中的情况几乎相同:

但我的情况是,如果用户尚未登录,登录访问将记录在数据库(房间)中, 然后系统将强制用户登录。 我过去经常申报 登录片段的目标

然后依次定义如下

  • 家庭碎片是开始的目标
  • 如果在数据库中未找到用户数据,则显示登录页面
  • 如果登录成功,请将用户带回主页并将登录数据保存到数据库
  • 我使用MVVM体系结构和协同程序来运行REST请求 使用改装

    以下是我使用的一些代码:

  • 导航(xml)

  • 家庭碎片

     class HomeFragment : Fragment() {
    
         ?? Should I usede LoginViewModel ?
    
         override fun onCreateView(
             inflater: LayoutInflater,
             container: ViewGroup?,
             savedInstanceState: Bundle?
         ): View? {
             return inflater.inflate(R.layout.fragment_home, container, false)
         }
    
         override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
             super.onViewCreated(view, savedInstanceState)
             observeAuthenticationState()
         }
    
         private fun observeAuthenticationState() {
             val navController = findNavController()
    
             // REDIRECT USER TO LOGIN PAGE ?
             // How To check it
             navController.navigate(R.id.action_global_loginFragment)
         }   
     }
    
  • 登录片段

     class LoginFragment : Fragment() {
    
         private lateinit var viewModel: LoginViewModel // How can I shared this to home fragment
         private lateinit var binding: FragmentLoginBinding
    
         override fun onCreateView(
             inflater: LayoutInflater,
             container: ViewGroup?,
             savedInstanceState: Bundle?
         ): View? {
    
             // For Retrofit
             val networkConnectionInterceptor = NetworkConnectionInterceptor(requireContext())
             val api = MyApi(networkConnectionInterceptor)
    
             // For Room
             val db = AppDatabase(context = requireActivity().applicationContext)
    
             // For ViewModel
             val repository = UserRepository(api, db)
             val factory = LoginViewModelFactory(repository)
    
             binding = DataBindingUtil.inflate(
                 inflater,
                 R.layout.fragment_login,
                 container,
                 false
             )
    
             viewModel = ViewModelProvider(this, factory).get(LoginViewModel::class.java)
             binding.buttonLogin.setOnClickListener { loginUser() }
             return binding.root
         }
    
         private fun loginUser() {
             val username = binding.editTextUsername.text.toString().trim()
             val password = binding.editTextPassword.text.toString().trim()
    
             binding.progressBar.show()
             lifecycleScope.launch {
                 try {
                     val loginResponse = viewModel.userLogin(username!!, password!!)
    
                     if(loginResponse.user != null){
                         viewModel.saveLoggedInUser(loginResponse.user)
                     }
    
                     binding.progressBar.hide()
                     binding.root.context.toast(loginResponse.message!!)
    
                 } catch (e: ApiException) {
                     binding.progressBar.hide()
                     binding.root.context.toast( e.toString())
                 } catch (e: NoInternetException) {
                     binding.progressBar.hide()
                     binding.root.context.toast( e.toString())
                 }
             }
         }
     }
    
  • 我的问题

  • 如何强制用户在主片段上正确登录片段
  • 如何在HomeFragment上使用LoginViewModel
  •  class HomeFragment : Fragment() {
    
         ?? Should I usede LoginViewModel ?
    
         override fun onCreateView(
             inflater: LayoutInflater,
             container: ViewGroup?,
             savedInstanceState: Bundle?
         ): View? {
             return inflater.inflate(R.layout.fragment_home, container, false)
         }
    
         override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
             super.onViewCreated(view, savedInstanceState)
             observeAuthenticationState()
         }
    
         private fun observeAuthenticationState() {
             val navController = findNavController()
    
             // REDIRECT USER TO LOGIN PAGE ?
             // How To check it
             navController.navigate(R.id.action_global_loginFragment)
         }   
     }
    
     class LoginFragment : Fragment() {
    
         private lateinit var viewModel: LoginViewModel // How can I shared this to home fragment
         private lateinit var binding: FragmentLoginBinding
    
         override fun onCreateView(
             inflater: LayoutInflater,
             container: ViewGroup?,
             savedInstanceState: Bundle?
         ): View? {
    
             // For Retrofit
             val networkConnectionInterceptor = NetworkConnectionInterceptor(requireContext())
             val api = MyApi(networkConnectionInterceptor)
    
             // For Room
             val db = AppDatabase(context = requireActivity().applicationContext)
    
             // For ViewModel
             val repository = UserRepository(api, db)
             val factory = LoginViewModelFactory(repository)
    
             binding = DataBindingUtil.inflate(
                 inflater,
                 R.layout.fragment_login,
                 container,
                 false
             )
    
             viewModel = ViewModelProvider(this, factory).get(LoginViewModel::class.java)
             binding.buttonLogin.setOnClickListener { loginUser() }
             return binding.root
         }
    
         private fun loginUser() {
             val username = binding.editTextUsername.text.toString().trim()
             val password = binding.editTextPassword.text.toString().trim()
    
             binding.progressBar.show()
             lifecycleScope.launch {
                 try {
                     val loginResponse = viewModel.userLogin(username!!, password!!)
    
                     if(loginResponse.user != null){
                         viewModel.saveLoggedInUser(loginResponse.user)
                     }
    
                     binding.progressBar.hide()
                     binding.root.context.toast(loginResponse.message!!)
    
                 } catch (e: ApiException) {
                     binding.progressBar.hide()
                     binding.root.context.toast( e.toString())
                 } catch (e: NoInternetException) {
                     binding.progressBar.hide()
                     binding.root.context.toast( e.toString())
                 }
             }
         }
     }