【Fragment多返回栈】开篇,Navigation 所谓的重建问题是什么?

前言

很高兴见到你 👋 我是 Flywith24,这是我在掘金发布的第 53 篇文章。android

「Fragment多返回栈」是一个新的系列,主要追踪官方对 Fragment 多返回栈这一功能的实现过程,透过该过程,咱们能够学习官方面对一个新功能是如何进行开发的。git

本文是该系列的开篇,内容分为三部分:github

  1. 简单介绍 Fragment 返回栈,并说明单返回栈与多返回栈的实现方式
  2. 简单解释 Navigation 所谓的重建 bug
  3. 简单梳理官方对此多返回栈功能支持的规划

本文对上述内容均是简单介绍,使用图片的方式形象地表述该部份内容(为此专门学习了 Sketch 🤣,我这么拼你好意思不点赞嘛?😋)。微信

关于源码详解,以及官方对此多返回栈功能支持所有时间线,可参考我以前的文章 【背上Jetpack之Navigation】想去哪就去哪,Android世界的指南针markdown

OK,让咱们开始吧~app

Fragment 还有返回栈?

提到返回栈,大多数小伙伴应该想到 Activity 返回栈。其实 Fragment 也是有返回栈的。关于 Fragment 的源码解析能够参考我以前写的 从源码的角度看Fragment 返回栈 附多返回栈demoide

简单总结一下 Fragment 的返回栈:oop

使用 addToBackStack() 方法能够将 Fragment 添加到返回栈。其内部将 mAddToBackStack 赋值为 true。post

FragmentManager 的实现类 FragmentManagerImpl 内部经过 ArrayList<BackStackRecord> mBackStack 管理返回栈。学习

若是 mAddToBackStack 为 true,则将 Fragment 加入到返回栈。

Fragment 单返回栈

现有 API,一个 FragmentMnager 只对应一个返回栈。咱们举一个形象的例子

以下图所示,Activity 中使用四个 FragmentContainerView 做为不一样花色扑克的容器。

其中每一个容器内会按牌面大小顺序发牌,如 ♥A → ♥2 → ♥3... 最终收牌时会严格按照发牌顺序进行回收。效果以下所示:

上述示例使用 Activity 的 FragmentManager 管理全部 Fragment,它们被组织在一个线性的结构里。咱们能够将其理解为 单返回栈

实现多返回栈

前文咱们提到,现有 API 一个 FragmentMnager 只对应一个返回栈,官方尚未提供单 FragmentMnager 管理多个返回栈的 API。那么咱们能够实现多返回栈吗?答案是能够的,咱们能够使用多个 FragmentManager 来实现。

如上图所示,绿色部分为 Fragment 容器,顶部四个 tab 分别对应不一样花色。建立四个 NavHostFragment(自定义的,与 navigation 无关)。点击其中一个花色 tab 便将对应的 NavHostFragment attach 到容器,并将其它 NavHostFragment dettach。最终效果以下:

这里的关键是使用了四个 NavHostFragment(上图中四个花色的 NavHostFragment 实例不一样)做为每一个返回栈的「宿主」,它们拥有本身的 FragmentManager,维护着本身的返回栈。

Navigation 所谓的 bug 到底是怎么回事?

Navigation 在管理带有平级关系的界面时会出现问题【背上Jetpack之Navigation】想去哪就去哪,Android世界的指南针 一文中已经探讨过该问题。

这里举例说明一下:

Navigation 重建问题

新建 Project,选择 Bottom Navigation Activity 模版:

该项目由一个 Activity(MainActivity) 以及三个 Fragment(Home,Dashboard,Notifications)组成。

结构示意图以下:

在内部,三个 Fragment(Home,Dashboard,Notifications)都由 androidx.navigation.fragment.NavHostFragment 管理,即便用 NavHostFragmentFragmentManager 管理返回栈。

每次点击底部按钮,都会新建 Fragment 实例(但它们的宿主未发生变化):

这里出现了不符合预期的现象,若是从 HomeFragment 点击跳转到 ChildFragment,点击 Dashboard 按钮后再点击 Home 按钮,因为 HomeFragment 重建,原来的 ChildFragment 消失。以下图:

该问题的本质

本质上,上面的示例是一个单返回栈的模型。由于三个 Fragment(Home,Dashboard,Notifications)都由 androidx.navigation.fragment.NavHostFragment 直接管理,而目前单个 FragmentManager 仅支持一个返回栈。

而这种平级的模型是须要多返回栈进行管理的,即 Home,Dashboard,Notifications 均拥有各自的返回栈。它们相互独立,互补影响。但以现有的 API 实现起来比较复杂,实现方式参考多返回栈一节。

官方出手了

上述问题早在 2018 年就已提出,地址 在这

而在 2021 年 1 月,官方终于开始着手解决这一问题。

该功能将在 Fragment 1.4.0 和 Navigation 2.4.0 版本提供。

总结

Navigation 管理带有平级关系的界面时,以现有的 API 会产生不符合预期的现象。本质上,该问题是因为现有的 API 不支持多返回栈形成的。好在官方已开始着手开发这一功能,该功能将在 Fragment 1.4.0 和 Navigation 2.4.0 版本提供。发布正式版可能须要一年多的时间。虽然很慢,好在有但愿。该系列会持续追踪这一过程,让咱们看看官方是如何在已有项目上进行新功能开发的吧~😉

咱们下期见。

关于我

人老是喜欢作可以得到正反馈(成就感)的事情,若是感受本文内容对你有帮助的话,麻烦点亮一下👍,这对我很重要哦~

我是 Flywith24人只有经过和别人的讨论,才能知道咱们本身的经验是不是真实的,加我微信交流,让咱们共同进步。


插入一点广告,掘金年度打榜投票正在进行中,若是个人文章对您有帮助的话,记得为我投票哦~ 点此投票

相关文章
相关标签/搜索