前言
很高兴见到你 👋
我是 Flywith24,这是我在掘金发布的 第56篇 原创文章。
本文是 Fragment 多返回栈系列的第二篇,主要介绍最新的 Fragment 多返回栈 API 以及新 API 是否仍会出现 Navigation Fragment 重建的问题。
让我们开始吧~
随着 Ian Lake 将这个 2018 年 5 月提的 issue 标记为 fixed,Android 终于支持了 Fragment 的多返回栈。
如果你是第一次接触 Fragment 多返回栈,可以移步以下内容以获取必要的前置知识:
- 【背上Jetpack之OnBackPressedDispatcher】Fragment 返回栈预备篇
- 【背上Jetpack之Fragment】从源码的角度看Fragment 返回栈 附多返回栈demo
- 【背上Jetpack】绝不丢失的状态 androidx SaveState ViewModel-SaveState 分析
- 【背上Jetpack之Fragment】从源码角度看 Fragment 生命周期 AndroidX Fragment1.2.2源码分析
- 【译】Fragment 的重大重构 —— 介绍 Fragment 新的状态管理器
- 【Fragment多返回栈】开篇,Navigation 所谓的重建问题是什么?
Fragment 支持多返回栈后解决了什么问题?
我们来简单回顾一下 Navigation 管理 「平级界面」 会遇到什么问题。详细内容可以 移步这里。
我们使用 Android Studio 的 bottom navigation 模板快速创建一个 project
该 project 由一个 Activity(MainActivity) 以及三个 Fragment(Home,Dashboard,
Notifications)组成,其中每个 tab 对应的父 Fragment 均可跳转到对应的子 Fragment 中:
每次点击底部 tab,对应的 Fragment 都会重新创建新的实例,这会导致当前 tab 之前存在的状态丢失,效果如下图:
上图中,在 Home tab 中点击进入
HomeChildFragment,此时点击dashboardtab 并返回,hometab 对应的 Fragment 恢复成原来的状态!这种行为完全不符合用户的预期。
我们将 navigation 库的版本调整到 2.4.0(目前在 alpha 阶段),该问题得到解决。
效果如下:
Fragment 支持多返回栈后就不重建了吗?
最近很多小伙伴反馈说使用版本的 Navigation 库仍然存在「重建」的问题。
我们使用新版本 Navigation 并点击每个 tab 查看当前 fragment 的实例:
上图可以看到,点击
dashboard和notificationstab 时,对应的 fragment 实例发生了变化(重复点击home并没重建 fragment,这个我们之后源码分析篇讨论)
新版本的 Navigation 仍会导致 fragment 的重建!
☝ 划重点
新版本的 Navigation 是如何恢复状态的?
通过前文我们已经知道新版本的 Navigation 仍会有 Fragment 的重建问题,那么如何使重建的 Fragment 能够恢复之前的状态?
答案呼之欲出:Android 的 SavedState 机制。更多关于 SavedState 的内容,可移步。
通过加入对 savedInstanceState 是否为空的判断日志我们了解到,每次重建 Fragment 时,savedInstanceState 不为空:
假设我们进行如下操作:
- 在初始化状态点击
dashboardtab 进入DashboardFragment,然后进入dashboard的详情页DashboardChildFragment - 之后点击
notificationstab 进入到NotificationsFragment - 最后点击
dashboard返回
步骤 1 执行完毕时 Saved State 与返回栈的状态:
步骤 2 执行完毕时 Saved State 与返回栈的状态:
步骤 2 执行时,Fragment Manager 会调用新 API
fragmentManager.saveBackStack("dashboard")将dashboard这个子返回栈(姑且这样称呼它)存入 Saved State
步骤 3 执行完毕时 Saved State 与返回栈的状态:
步骤 3 执行时,Fragment Manager 会调用新 API
fragmentManager.saveBackStack("notifications"),fragmentManager.restoreBackStack("dashboard")保存 notifications 的子返回栈,恢复 dashboard 的子返回栈。
这样表述你明白了吗? 😉
具体的实现逻辑我们将在源码篇介绍,敬请期待。
关于我
人总是喜欢做能够获得正反馈(成就感)的事情,如果感觉本文内容对你有帮助的话,麻烦点亮一下👍,这对我很重要哦~
我是 Flywith24,人只有通过和别人的讨论,才能知道我们自己的经验是否是真实的,加我微信交流,让我们共同进步。