【发布时间】:2021-08-03 14:45:24
【问题描述】:
前几天我开始注意到我的应用中有一些东西,而且非常不一致。有时会发生,有时不会。
我正在使用导航组件来处理应用程序中的导航,我开始注意到有时,当通过操作栏后退按钮或设备后退按钮弹出后退堆栈时,它会返回到不再是起始目的地的片段(或者至少不应该)。
在我的例子中,应用程序从 MainFragment 开始,一旦经过身份验证,就会移动到 DashboardFragment。这是很常见的情况。
应用程序中的导航非常平坦。大多数情况下,它只有 1 级深度,因此几乎所有视图都可以从仪表板访问。
应用程序从登录视图开始,然后到仪表板,会话将保留为“起始目的地”。为此,它使用 popUpTo 和 popUpToInclusive 在 nav_graph 中完成。
<fragment
android:id="@+id/mainFragment"
android:name="com.example.view.fragments.MainFragment"
android:label="Welcome">
<action
android:id="@+id/action_mainFragment_to_dashboardFragment"
app:destination="@id/dashboardFragment"
app:popUpTo="@id/mainFragment"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="@+id/dashboardFragment"
android:name="com.example.view.fragments.dashboard.DashboardFragment"
android:label="@string/dashboard_header" >
<action
android:id="@+id/action_dashboardFragment_to_notificationsFragment"
app:destination="@id/notificationsFragment" />
</fragment>
当用户成功验证并进入仪表板时,我使用 NavController.navigate() 将它们发送到那里。
findNavController().navigate(
MainFragmentDirections.actionMainFragmentToDashboardFragment()
)
// This should have the same result and it does appear to be affected by the same issue
// findNavController().navigate(R.id.action_mainFragment_to_dashboardFragment)
我有一个带有后退箭头和导航抽屉的操作栏。在主要活动中,我需要定义 AppBarConfiguration 并覆盖 onSupportNavigateUp()
lateinit var appBarConfiguration: AppBarConfiguration
...
override fun onCreate(savedInstanceState: Bundle?) {
Timber.d("onCreate()")
super.onCreate(savedInstanceState)
_binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// There is 2 different drawer menu's respectfully.
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.mainFragment,
R.id.dashboardFragment
), binding.drawerLayout
)
setSupportActionBar(binding.toolbar)
setupActionBarWithNavController(navController, appBarConfiguration)
}
...
override fun onSupportNavigateUp(): Boolean {
Timber.d("-> onSupportNavigateUp()")
val breadcrumb = navController
.backStack
.map { it.destination }
.filterNot { it is NavGraph }
.joinToString(" > ") { it.displayName.split('/')[1] }
Timber.d("Backstack: $breadcrumb")
Timber.d("Previous backstack entry: ${navController.previousBackStackEntry?.destination?.displayName}")
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
...
当我们退后一步时,日志看起来像这样,它工作正常
D/MainActivity: -> onSupportNavigateUp()
D/MainActivity: Backstack: dashboardFragment > testingFragment
D/MainActivity: Previous backstack entry: com.example:id/dashboardFragment
D/DashboardFragment: -> onCreateView()
D/BaseFragment: -> onCreateView()
D/DashboardFragment: -> onViewCreated()
我还注意到在操作栏中使用汉堡包时,它也会调用 onSupportNavigateUp()
D/MainActivity: -> onSupportNavigateUp()
D/MainActivity: pendingAction: false
D/MainActivity: Backstack: dashboardFragment
D/MainActivity: Previous backstack entry: null
当我使用抽屉导航到目的地时,我确实在日志中看到了这一点,但我不确定返回的位置/原因,或者它是否有任何重要性
I/NavController: Ignoring popBackStack to destination com.example:id/mainFragment as it was not found on the current back stack
现在,当它的 不 正常工作时,这就是日志的样子
D/MainActivity: -> onSupportNavigateUp()
D/MainActivity: Backstack: mainFragment > testingFragment
D/MainActivity: Previous backstack entry: com.example:id/mainFragment
D/MainFragment: -> onCreateView()
D/BaseFragment: -> onCreateView()
D/MainFragment: -> onViewCreated()
当执行从主片段到仪表板片段的导航时,这真的感觉就像 popUpTo 和 popUpToInclusive 属性没有被应用(有时)。同样令人怀疑的是,即使仪表板片段未设置为新的起始目的地,但它也从后台堆栈中丢失。假设未应用属性,我希望看到面包屑Backstack: mainFragment > dashboardFragment > testingFragment
任何帮助将不胜感激!
【问题讨论】:
-
根据Principles of Navigation,您的欢迎片段绝对不应该是图表的起始目的地。对于这种情况,有一个指南 specifically about conditional navigation。
-
@ianhanniballake 应用的欢迎片段是登录片段。没有其他视图(如登陆/欢迎视图)在登录和仪表板之间进行分类。如果用户正确登录,它应该移动到仪表板并设置为新的起点。这样一来,如果应用程序关闭并且在应用程序超时期限内,我们将跳过登录并跳回仪表板。将另一个片段添加到此组合中不会显示视图,因此仅用于逻辑,然后从登录或仪表板退回将需要处理退出应用程序。
-
这不是那些文档所说的。他们说您的仪表板目标应该是起始目标,并且它应该负责有条件地在用户未登录时将其导航到登录屏幕。
-
@ianhanniballake 根据您的陈述并将我的应用程序结构应用于条件导航示例,您是说我的起始目的地将是个人资料片段。未经身份验证,无法使用此应用程序。登录视图是唯一可以在未经身份验证的情况下看到的视图。假设我将仪表板设置为起始目的地并有条件地重定向到登录,然后我需要将其设置为起始目的地以将用户隔离到该视图。如果他们向上/向后导航,则会返回到必须对其进行身份验证的仪表板。
-
您的仪表板将是起始目的地 - 导航原则特别指出的固定起始目的地。
标签: android kotlin android-fragments android-architecture-navigation