导航架构组件 - 登录屏幕

Yas*_*yan 5 java android kotlin android-architecture-navigation

我打算像这样实现导航:
在此输入图像描述
我面临的问题是当用户进入LoginFragmennt并按下后退按钮时,它再次加载LognFragment即.卡在循环中.

我LoginnFragment按照这个答案导航到使用条件导航.

如何正确实现这个?

Car*_*mer 8

恕我直言我在我的应用程序中如何做到这一点是一个更清洁.只需在导航图中添加以下设置:

<fragment
    android:id="@+id/profile_dest"
    android:name="com.example.ProfileFragment">
    <action
        android:id="@+id/action_profile_dest_to_login_dest"
        app:destination="@id/login_dest"
        app:popUpTo="@+id/profile_dest"
        app:popUpToInclusive="true" />       
</fragment>
Run Code Online (Sandbox Code Playgroud)

然后导航到登录

findNavController().navigate(R.id.action_profile_dest_to_login_dest).

ProfileFragment当我们导航到popUpTo和popUpToInclusive关闭时LoginFragment,如果用户导航回来,它将退出应用程序.

  • 对,就是这样。就像问题中的图表所示。此操作还应关闭(从后台堆栈中删除)登录屏幕。 (2认同)

Ale*_*lex 5

我可以建议的解决方案之一就是覆盖你的活动onBackPressed方法,如果你当前的目的地(在后面按下处理之前)是登录片段,则完成活动.

override fun onBackPressed() {
    val currentDestination=NavHostFragment.findNavController(nav_host_fragment).currentDestination
    when(currentDestination.id) {
        R.id.loginFragment -> {
            finish()
        }
    }
    super.onBackPressed()
}
Run Code Online (Sandbox Code Playgroud)

  • exit(0)将终止你的应用程序,完成()完成你的活动.不要使用exit(0). (4认同)

Val*_*kov 2

以下是 Ian Lake 在2020 年 7 月 23 日Android 开发者YouTube 频道上的Navigating 导航视频中建议的官方解决方案。该解决方案基于导航2.3 版本,该版本引入了将结果返回到先前目的地的功能。

在我们的例子中,登录片段将LOGIN_SUCCESSFUL状态返回到先前的目的地,它可能是配置文件片段或任何其他需要登录的片段。

class LoginFragment : Fragment(R.layout.login) {
    ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val navController = findNavController()
        val savedStateHandle = navController.previousBackStackEntry?.savedStateHandle
            ?: throw IllegalStateException("the login fragment must not be a start destination")
            
        savedStateHandle.set(LOGIN_SUCCESSFUL, false)
        // Hook up your UI, ask for login
        
        userRepository.addLoginSuccessListener {
            savedStateHandle.set(LOGIN_SUCCESSFUL, true)
            navController.popBackStack()
        } 
    }
}
Run Code Online (Sandbox Code Playgroud)

配置文件片段订阅状态LOGIN_SUCCESSFUL并处理它。请注意,在登录片段将结果放入并返回到配置文件片段之前,不会调用观察者 lambda。

class ProfileFragment : Fragment(R.layout.profile) {
    ...
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val navController = findNavController()
        viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            userRepository.userFlow.collect { user -> 
                if (user == null) {
                    navController.navigate(R.id.login)
                }
            }
        }
        
        val savedStateHandle = navController.currentBackStackEntry?.savedStateHandle
            ?: throw IllegalStateException()
        
        savedStateHandle.getLiveData<Boolean>(LOGIN_SUCCESSFUL)
            .observe(viewLifecycleOwner) { success -> 
                if (!success) {
                    // do whathever we want, just for an example go to
                    // the start destination which doesn't require login
                    val startDestination = navController.graph.startDestination
                    navController.navigate(startDestination, navOptions {
                        popUpTo(startDestination {
                            inclusive = true
                        })
                    })
                }
            }
    }
}
Run Code Online (Sandbox Code Playgroud)