flutter:AutomaticKeepAliveClientMixin

  1. 是什么
  2. 为什么需要它
  3. 完整代码示例
  4. 如何使用
  5. 工作机制
  6. super.build(context)
    1. super与build
    2. 为什么要 super.build(context)?

是什么

它是 Flutter SDK 提供的一个 Mixin

作用是:当 Widget 离开屏幕(比如 Tab 页切换),可以让它的 State 不会被销毁,从而保持页面状态

官方定义:mixin AutomaticKeepAliveClientMixin<T extends StatefulWidget> on State<T>

  • on State:必须混入到 StatefulWidget 的 State 类里使用。

为什么需要它

默认情况下,Flutter 的 ListView、PageView、TabBarView 出于性能考虑,会 销毁不可见的页面(状态 dispose 掉,重新进入时又会 rebuild)。

这样带来两个问题:

  • 输入框内容丢失;
  • 滑动位置重置;
  • 请求过的数据需要重新加载。

AutomaticKeepAliveClientMixin 的目的就是:即使页面不可见,也保持它的 State 不被销毁。

完整代码示例

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'KeepAlive Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2, // 两个标签页
      child: Scaffold(
        appBar: AppBar(
          title: const Text("AutomaticKeepAliveClientMixin 示例"),
          bottom: const TabBar(
            tabs: [
              Tab(text: "没有 KeepAlive"),
              Tab(text: "有 KeepAlive"),
            ],
          ),
        ),
        body: const TabBarView(children: [NoKeepAlivePage(), KeepAlivePage()]),
      ),
    );
  }
}

// ========== 页面1:没有使用 AutomaticKeepAliveClientMixin ==========
class NoKeepAlivePage extends StatefulWidget {
  const NoKeepAlivePage({super.key});

  @override
  State<NoKeepAlivePage> createState() => _NoKeepAlivePageState();
}

class _NoKeepAlivePageState extends State<NoKeepAlivePage> {
  int counter = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text("Counter: $counter", style: const TextStyle(fontSize: 24)),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() => counter++),
        child: const Icon(Icons.add),
      ),
    );
  }
}

// ========== 页面2:使用 AutomaticKeepAliveClientMixin ==========
class KeepAlivePage extends StatefulWidget {
  const KeepAlivePage({super.key});

  @override
  State<KeepAlivePage> createState() => _KeepAlivePageState();
}

class _KeepAlivePageState extends State<KeepAlivePage>
    with AutomaticKeepAliveClientMixin {
  int counter = 0;

  @override
  bool get wantKeepAlive => true; // 保持状态

  @override
  Widget build(BuildContext context) {
    super.build(context); // 必须调用
    return Scaffold(
      body: Center(
        child: Text("Counter: $counter", style: const TextStyle(fontSize: 24)),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() => counter++),
        child: const Icon(Icons.add),
      ),
    );
  }
}

如何使用

  1. 混入 AutomaticKeepAliveClientMixin
  2. wantKeepAlive => true
  3. super.build(context) 不能忘。

工作机制

AutomaticKeepAliveClientMixin 的工作机制是:

  • 你的 State 混入了这个 Mixin,它会和 Flutter 的 KeepAlive 机制交互。
  • 当 Flutter 构建 TabBarViewPageView 等滚动组件时,会询问子页面:“你要不要保持存活?”
  • 这个询问是通过 super.build(context) 触发的。

换句话说:

  • 如果你 不调用 super.build(context)KeepAlive 的信息(wantKeepAlive)就不会传递到父级。
  • Flutter 就不知道你要保持页面,于是页面在切换后仍会被销毁(表现和没加 Mixin 一样)。

super.build(context)

super与build

class _KeepAlivePageState extends State<KeepAlivePage>
    with AutomaticKeepAliveClientMixin {
  int counter = 0;

  @override
  bool get wantKeepAlive => true; // 保持状态

  @override
  Widget build(BuildContext context) {
    super.build(context); // 必须调用
    return Scaffold(
      body: Center(
        child: Text("Counter: $counter", style: const TextStyle(fontSize: 24)),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() => counter++),
        child: const Icon(Icons.add),
      ),
    );
  }
}

问题一:_KeepAlivePageState重写的是谁的build?答:AutomaticKeepAliveClientMixin

class _KeepAlivePageState extends State<KeepAlivePage>
    with AutomaticKeepAliveClientMixin {

Dart 的方法解析顺序 (MRO) 是:_KeepAlivePageState → AutomaticKeepAliveClientMixin → State

  • 它会先找 _KeepAlivePageState 有没有 build。如果没有,就再往后面找。
  • 所有,我这里重写的是AutomaticKeepAliveClientMixin的build方法。

问题二:super是指哪个?指**AutomaticKeepAliveClientMixin**

class _KeepAlivePageState extends State<KeepAlivePage>
    with AutomaticKeepAliveClientMixin {

在 Dart 中,super 指的并不是某个“固定的类”,而是:当前类的直接父类或混入链中的上一个实现

  • 如果某个方法在 mixin 里有实现,那么 super 就会指向混入链中“上一个”的实现;
  • 如果 mixin 没有实现该方法,super 就会指向 extends 的父类。

上面案例类的继承关系

State<KeepAlivePage>  <-- 父类
↑
AutomaticKeepAliveClientMixin   <-- 混入,覆盖了 build()
↑
_KeepAlivePageState  <-- 你写的类

为什么要 super.build(context)

// AutomaticKeepAliveClientMixin 里的 build 源码
@mustCallSuper
@override
Widget build(BuildContext context) {
  if (wantKeepAlive && _keepAliveHandle == null) {
    _ensureKeepAlive();
    // Whenever wantKeepAlive's value changes (or might change), the
    // subclass should call [updateKeepAlive].
    // That will ensure that the keepalive is disabled (or enabled)
    // without requiring a rebuild.
  }
  return const _NullWidget();
}
}
  • AutomaticKeepAliveClientMixinbuild 方法不会去渲染 UI,而是负责 插入 KeepAlive 逻辑
  • 它会检查 wantKeepAlive 是否为 true,如果是,就调用 _ensureKeepAlive(),让 Flutter 知道 这个 Widget 不要被销毁
  • 返回的 _NullWidget() 本质上只是个占位,它不会显示在界面上(真正的 UI 是你在 State.build 里写的 Scaffold 等)。

×

喜欢就点赞,疼爱就打赏