Flutter Tabbar 切换不要每次初始化

一、Tabbar 切换不要每次初始化

  • 方式一:用 IndexedStack 就行了,比如 IndexedStack 管理着 a b c 页面,然后 a 跳转到 d 页面,d 不会被缓存。因为 IndexedStack 只控制显示的页面,而不直接控制页面内的导航栈(Navigator)。

  • 方式二:AutomaticKeepAliveClientMixin 则是只针对 StatefulWidget 且只希望在页面切换时保持部分页面的状态,使用 AutomaticKeepAliveClientMixin 更加灵活且节省内存。

二、详细介绍

1. IndexedStack

使用场景:

IndexedStack 适用于你希望在多个页面之间切换时,保留所有页面的状态(即每个页面只初始化一次,后续切换时不会重新构建页面)。如果你有多个标签页,且每个标签页都有独立的状态,使用 IndexedStack 可以确保所有页面都保持在内存中,不会丢失数据。

作用:
  • IndexedStack 会创建一个包含所有页面的堆栈,并根据当前的索引选择显示哪个页面。每次切换 Tab 时,之前的页面会保持在堆栈中,而不会被销毁或重新创建。
总结:
  • 优点:适合需要保留所有页面状态的情况。
  • 缺点:会消耗更多的内存,特别是在页面比较复杂或数量较多时,因为所有页面都被保留在内存中。

2. PageStorage 和 PageStorageKey

使用场景:

适用于希望在切换页面时保存单个页面的状态(如滚动位置、表单输入等),特别是在需要跨页面切换但又不希望重新加载或重置页面状态时。常用于 ListViewGridView 等有滚动或其他状态的页面。

作用:
  • PageStorage 可以在页面切换时保存和恢复页面的状态,使用 PageStorageKey 为每个页面分配唯一的标识符。Flutter 会自动保存每个页面的状态(如滚动位置),并在页面重新显示时恢复。
总结:
  • 优点:适合只需要保存某个页面的小范围状态(如滚动条位置等)。
  • 缺点:需要手动管理 PageStorageKey,且不适用于整个页面的状态保存,更多是适用于特定的组件或视图。

3. AutomaticKeepAliveClientMixin

使用场景:

适用于在 StatefulWidget 中,当你希望在页面切换时保持每个页面的状态(如表单输入、动画状态等)。如果你有多个页面,并且希望每个页面的状态都被保留,可以将该 mixin 应用于每个页面的 State 类。

作用:
  • 通过实现 AutomaticKeepAliveClientMixin,并将 wantKeepAlive 设置为 true,你可以确保页面的状态在切换时保持不变。这个方法通常用于控制多个页面状态是否应该被保持。
总结:
  • 优点:非常适合需要在多个 StatefulWidget 中保持状态的场景。
  • 缺点:需要在每个页面的 State 类中实现并正确配置,可能会增加一些代码复杂度。

4. Navigator 和 StatefulWidget

使用场景:

适用于你希望在每个 Tab 页中保持独立的导航历史栈的情况。通常在需要保持每个 Tab 页面内部的导航状态(比如你在 Home Tab 下有一个跳转到 Detail 页的需求)时,可以在每个页面使用 Navigator

作用:
  • Navigator 允许每个 Tab 页面拥有独立的导航栈。这使得每个页面都可以进行独立的页面跳转,而不影响其他页面的导航历史。
总结:
  • 优点:适合需要在每个 Tab 内进行独立导航的情况,例如每个 Tab 页面内都需要管理独立的页面跳转。
  • 缺点:会增加代码复杂度,尤其是在管理多个 Navigator 时,可能需要一些额外的逻辑。

5. TabController 和 TabBarView

使用场景:

适用于使用 TabBarTabBarView 进行页面切换的场景,尤其是在你希望保持页面状态时(比如滚动位置、表单状态等)。通常用于带有选项卡(Tab)的界面,Tab 内部的页面通常是独立的,且需要保持状态。

作用:
  • TabController 用于管理 Tab 页的状态(当前选中的 Tab)。TabBarView 是用于显示 Tab 页内容的组件,它会自动与 TabController 配合工作来显示相应的页面。
  • 若结合 AutomaticKeepAliveClientMixin,可以在切换 Tab 时保留页面的状态。
总结:
  • 优点:非常适合常见的 Tab 页面切换场景,特别是与 TabController 配合使用时,可以轻松管理 Tab 页的切换。
  • 缺点:适用场景较为局限,只适用于 Tab 页面之间的切换,且如果不与 AutomaticKeepAliveClientMixin 一起使用,页面会在切换时被销毁。

总结与选择

  • IndexedStack:适合需要保留所有页面状态的场景,尤其是 Tab 页切换时,不希望每个页面重新构建。
  • PageStorage:适用于需要保存特定页面状态的情况,特别是列表滚动、表单输入等小范围状态。
  • AutomaticKeepAliveClientMixin:适合保持每个页面的状态,特别是当页面是 StatefulWidget 时。
  • Navigator 和 StatefulWidget:适用于需要在每个 Tab 页中管理独立导航历史栈的复杂场景。
  • TabController 和 TabBarView:适用于标准的 Tab 页面切换,搭配 AutomaticKeepAliveClientMixin 可以保持状态。

选择的方法主要取决于你需要管理的页面状态的范围和复杂度。如果只是需要在 Tab 页面间切换并保持状态,IndexedStackTabController 配合 AutomaticKeepAliveClientMixin 是不错的选择。如果页面复杂并且需要独立的导航栈,Navigator 可能更适合。