我正在尝试实现android jetpack导航组件。 该案例与官方文档中的案例几乎相同:https://developer.android.com/guide/navigation/navigation-conditional
但是我的情况是,如果用户尚未登录,那么登录访问将记录在数据库(房间)中, 然后系统将强制用户登录。 我用https://developer.android.com/guide/navigation/navigation-global-action声明 登录片段的目的地
然后依次定义如下
我使用MVVM体系结构和协程,它们对REST运行请求 使用翻新。
以下是我使用的一些代码:
导航(xml)
<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/nav"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.depo.trask.ui.home.HomeFragment"
android:label="@string/app_name"
tools:layout="@layout/fragment_home">
<argument android:name="authentication"
android:defaultValue="none" />
<action
android:id="@+id/action_homeFragment_to_settingsFragment"
app:destination="@id/settingsFragment" />
</fragment>
<fragment
android:id="@+id/settingsFragment"
android:name="com.depo.trask.ui.settings.SettingsFragment"
android:label="@string/settings" />
<fragment
android:id="@+id/loginFragment"
android:name="com.depo.trask.ui.login.LoginFragment"
android:label="fragment_login"
tools:layout="@layout/fragment_login" />
<action
android:id="@+id/action_global_loginFragment"
app:destination="@id/loginFragment"
app:launchSingleTop="false"
app:popUpTo="@+id/nav_host_fragment"
app:popUpToInclusive="true" />
</navigation>
MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
private lateinit var bottomNavigationView: BottomNavigationView
private lateinit var toolbar: Toolbar
private val navigationInMainScreen = setOf(
R.id.loginFragment,
R.id.homeFragment,
R.id.containerShippingFragment,
R.id.locationFragment,
R.id.historyFragment,
R.id.aboutFragment
)
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.Theme_MyTheme)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupNavController()
}
override fun onSupportNavigateUp(): Boolean {
navController.navigateUp()
return super.onSupportNavigateUp()
}
// Nav Controller
private fun setupNavController() {
navController = findNavController(R.id.nav_host_fragment)
setupActionBar()
setupBottomNavigationBar()
navController.addOnDestinationChangedListener { _, destination, _ ->
// Listening toolbar
when(destination.id){
R.id.loginFragment, R.id.aboutFragment -> toolbar.visibility = View.GONE
else -> toolbar.visibility = View.VISIBLE
}
// Listening bottom navigation bar
when (destination.id) {
R.id.loginFragment, R.id.settingsFragment -> bottomNavigationView.visibility = View.GONE
else -> bottomNavigationView.visibility = View.VISIBLE
}
}
}
// Top Bar OR App Bar
private fun setupActionBar() {
toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
val appBarConfiguration = AppBarConfiguration(
navigationInMainScreen
)
setupActionBarWithNavController(navController, appBarConfiguration)
}
// Bottom Navigation Bar
private fun setupBottomNavigationBar() {
bottomNavigationView = findViewById(R.id.bottom_navigation_view)
bottomNavigationView.setupWithNavController(navController)
}
}
首页片段
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())
}
}
}
}
我的问题吗?