Flutter基础 — Flutter基础特性

作者 : admin 本文共16191个字,预计阅读时间需要41分钟 发布时间: 2024-06-4 共3人阅读

目录

1. 一切都是 widget

1.1 UI 组件!!!

1.2 架构设计

1.3 sdk 源码目录

1.4 widget 分类!!!

参考文献

2. devTools 调试工具

2.1 启动调试器

2.2 布局面板

参考文献

3. 布局约束规则

3.1 让子元素竟可能的大,撑满父元素

3.2 确认位置后,按子元素大小显示

3.3 核心规则:Constraints go down. Sizes go up. Positions are set by parents.

参考文献

4. 松约束

4.1 Column 宽度等于子元素最大宽度

4.2 Container 会紧包裹子元素

4.3 松约束定义

参考文献

5. 紧约束

5.1 ConstrainedBox 约束组件

5.2 紧约束定义

6. 无边界 unbounded

6.1 UnconstrainedBox 不受约束

6.2 unbounded 组件

7. 有状态无状态组件

7.1 无状态 StatelessWidget

7.2 有状态 StatefulWidget

7.3 有状态包裹无状态组件

7.4 使用函数编写组件

参考文献

8. 生命周期

8.1 StatefulWidget 生命周期

8.2 StatelessWidget 生命周期

8.3 App生命周期


1. 一切都是 widget

1.1 UI 组件

这有三个帮助开发的文档,主要推荐 2和3,直观一点

Widgets | Flutter

Flutter基础 — Flutter基础特性插图

Flutter 画廊 (flutter-gallery-archive.web.app)

Flutter基础 — Flutter基础特性插图(1)

flutter_catalog

Flutter基础 — Flutter基础特性插图(2)

如果需要什么组件,可以先去以上两个网址看看有现成的能否满足需求        

1.2 架构设计

Flutter基础 — Flutter基础特性插图(3)

Flutter基础 — Flutter基础特性插图(4)

Flutter基础 — Flutter基础特性插图(5)

渲染引擎

http://skia.org/

1.3 sdk 源码目录

sdk/packages/flutter/lib/src

Flutter基础 — Flutter基础特性插图(6)

Flutter基础 — Flutter基础特性插图(7)

1.4 widget 分类

Flutter基础 — Flutter基础特性插图(8)

  • 基础组件 Widget(Basics):

Container、Row、Column、Image、Text、Icon、RaisedButton、Scaffold、Appbar、FlutterLogo、Placeholder

  • Material Components:

  • App 结构和导航类

Scaffold、Appbar、BottomNavigationBar、TabBar、TabBarView、MaterialApp、WidgetsApp、Drawer、SliverAppBar

  • 按钮类

RaisedButton、FloatingActionButton、FlatButton、IconButton、DropdownButton、PopupMenuButton、ButtonBar

  • 输入和选择类

TextField、Checkbox、Raido、Switch、Slider、Date&Time Pickers

  • 对话框和控制面板类

SimpleDialog、AlertDialog、BottomSheet、ExpansionPanel、SnackBar);

信息显示类(Image、Icon、Chip、Tooltip、DataTable、Card、LinearProgressIndicator、CircularProgressIndicator、GridView

  • 布局类

ListTile、Stepper、Divider

  • Cupertino (iOS-style widgets):

CupertinoActionSheet、CupertinoActivityIndicator、CupertinoAlertDialog、CupertinoButton、CupertinoDatePicker、CupertinoDialog、CupertinoDialogAction、CupertinoFullscreenDialogTransition、CupertinoPageScaffold、CupertinoPageTransition、CupertinoPicker、CupertinoPopupSurface、CupertinoSegmentedControl、CupertinoSlider、CupertinoSwitch、CupertinoNavigationBar、CupertinoTabBar、CupertinoTabScaffold、CupertinoTabView、CupertinoTextField、CupertinoTimerPicker

  • Layout:

  • 单个子元素的布局 Widget

Container、Padding、Center、Align、FittedBox、AspectRatio、ConstrainedBox、Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth、LimitedBox、Offstage、OverflowBox、SizedBox、SizedOverflowBox、Transform、CustomSingleChildLayout

  • 多个子元素的布局 Widget

Row、Column、Stack、IndexedStack、GridView、Flow、Table、Wrap、ListBody、CustomMultiChildLayout、LayoutBuilder、ListView、Expanded

  • Text 文本显示类:

Text、RichText、DefaultTextStyle

  • Assets、图片、Icons 类:

Image、Icon、RawImage、AssetBundle

  • Input 输入类:

Form、FormField、RawKeyboardListener

  • 动画和 Motion 类:

AnimatedContainer、AnimatedCrossFade、Hero、AnimatedBuilder、DecoratedBoxTransition、FadeTransition、PositionedTransition、RotationTransition、ScaleTransition、SizeTransition、SlideTransition、AnimatedDefaultTextStyle、AnimatedListState、AnimatedModalBarrier、AnimatedOpacity、AnimatedPhysicalModel、AnimatedPositioned、AnimatedSize、AnimatedWidget、AnimatedWidgetBaseState

  • 交互模型类:

  • 触摸交互

Draggable、LongPressDraggable、GestureDetector、DragTarget、Dismissible、IgnorePointer、AbsorbPointer、Scrollable

  • 路由导航

Hero、Navigator

  • 样式类:

Padding、Theme、MediaQuery

  • 绘制和效果类:

Transform、Opacity、DecoratedBox、FractionalTranslation、RotatedBox、ClipOval、ClipPath、ClipRect、CustomPaint、BackdropFilter

  • Async 异步模型类:

FutureBuilder、StreamBuilder

  • 滚动类:

GridView、ListView、NestedScrollView、SingleChildScrollView、Scrollable、Scrollbar、CustomScrollView、NotificationListener、ScrollConfiguration、RefreshIndicator、PageView

  • 辅助功能类:

Semantics、MergeSemantics、ExcludeSemantics

参考文献

  • http://github.com/flutter/gallery
  • http://gallery.flutter.dev/
  • Widgets | Flutter

2. devTools 调试工具

2.1 启动调试器

  • 启动调试后
    • 1 点击右上角按钮
    • 2 点击选中按钮
    • 3 布局浏览器

Flutter基础 — Flutter基础特性插图(9)

  • 命令模式 Dart: Open DevTools

cmd + shift + p 启动命令

Flutter基础 — Flutter基础特性插图(10)

  • 我们选择 in web browser

Flutter基础 — Flutter基础特性插图(11)

  • 如果是第一次打开,选择允许打开 always open
  • 会在浏览器中打开调试界面
  • 面板选项
    • Flutter Inspector 布局组件
    • Performance 性能
    • CPU Profiler 耗能
    • Memory 内存
    • Debugger 调试信息
    • Network 抓包
    • Logging 日志
    • App Size 文件打包尺寸分析

Flutter基础 — Flutter基础特性插图(12)

性能模式要创建launch.json文件,选择第二个模式(第一个是传统debug;第二个是性能模式;第三个是release)

Flutter基础 — Flutter基础特性插图(13)

2.2 布局面板

  • 说明
    • 1 组件树
    • 2 纵向布局信息
    • 3 横向布局信息
    • 4 约束信息

Flutter基础 — Flutter基础特性插图(14)

参考文献

Flutter and Dart DevTools | Flutter

3. 布局约束规则

3.1 让子元素竟可能的大,撑满父元素

在 main 函数中,直接创建 Container 显示

void main(List args) {
  runApp(build());
}

Widget build() {
  return Container(
    width: 200,
    height: 200,
    color: Colors.amber,
  );
}

Flutter基础 — Flutter基础特性插图(15)

3.2 确认位置后,按子元素大小显示

用 Center 包裹 Container

void main(List args) {
  runApp(build());
}

Widget build() {
  return Center(
    child: Container(
      width: 200,
      height: 200,
      color: Colors.amber,
    ),
  );
}

Flutter基础 — Flutter基础特性插图(16)

3.3 核心规则:Constraints go down. Sizes go up. Positions are set by parents.

  • 层 widget 向下层 widget 传递约束条件
  • 下层 widget 向层 widget 传递大小信息
  • 层 widget 决定下层 widget 的位置

Flutter基础 — Flutter基础特性插图(17)

我们写3个文字组件纵向排列

Widget _buildScaffold() {
  return Scaffold(
    body: Column(
      children: const [
        Text("aaaaaa"),
        Text("bbbbb"),
        Text("cccc"),
      ],
    ),
  );
}

Flutter基础 — Flutter基础特性插图(18)

宽度 0.0 <= w <= 303.0 , 高度 0.0 <= h <= 523.0 ,就是上层传下来的约束

Flutter基础 — Flutter基础特性插图(19)

宽度 w=32.0 , 高度 h=16.0 就是组件向上层传递的大小信息

Flutter基础 — Flutter基础特性插图(20)

元素左边 w=7.5,右边 w=7.5,就是上层决定下层的组件位置

Flutter基础 — Flutter基础特性插图(21)

参考文献

http://medium.com/flutter-community/flutter-the-advanced-layout-rule-even-beginners-must-know-edc9516d1a2

http://juejin.cn/post/6846687593745088526

Understanding constraints | Flutter

4. 松约束

4.1 Column 宽度等于子元素最大宽度

就是说子元素宽带如果增加到比Column的宽度还大,Column也会随着增加宽度

import 'package:flutter/material.dart';

void main() {
  runApp(build());
}

Widget build() {
  return MaterialApp(
    home: Scaffold(
      body: Column(
        children: const [
          Text("aaaaaaaaaaaaaaaaaaaaaa"),
          Text("aaaaaaaaaaa"),
        ],
      ),
    ),
  );
}

Flutter基础 — Flutter基础特性插图(22)

Flutter基础 — Flutter基础特性插图(23)

4.2 Container 会紧包裹子元素

Scaffold 填充了整个屏幕,Container 包裹了 Column

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          color: Colors.amber,
          child: Column(
            children: const [
              Text("aaaaaaaaaaaaaaaa"),
              Text("bbbbbbbbb"),
            ],
          ),
        ),
      ),
    );
  }
}

Flutter基础 — Flutter基础特性插图(24)

Container 的宽高随着 Column 一起变化 w = 124.0,紧包裹

Flutter基础 — Flutter基础特性插图(25)

4.3 松约束定义

当一个 widget 告诉其子级可以比自身更小的话, 我们通常称这个 widget 对其子级使用 宽松约束(loose),意思就是说,比如有(0.0<=w<=375.0)范围这种,就是松约束

Scaffold 对 Column 的约束是宽高屏幕宽度内即可

Flutter基础 — Flutter基础特性插图(26)

Column 的宽度按 Text 最大宽度为准

Flutter基础 — Flutter基础特性插图(27)

参考文献

BoxConstraints class – rendering library – Dart API

5. 紧约束

5.1 ConstrainedBox 约束组件

constraints 通过 maxWidth maxHeight ,来设置子组件最大约束

void main() {
  runApp(build());
}

Widget build() {
  return MaterialApp(
    home: Scaffold(
      body: Center(
        child: ConstrainedBox(
          constraints: const BoxConstraints(
            maxWidth: 200,
            maxHeight: 200,
          ),
          child: Container(
            color: Colors.amber,
            width: 50,
            height: 50,
          ),
        ),
      ),
    ),
  );
}

显示了一个 50 x 50 的 Container

Flutter基础 — Flutter基础特性插图(28)

我们加上 minWidth minHeight

void main() {
  runApp(build());
}

Widget build() {
  return MaterialApp(
    home: Scaffold(
      body: Center(
        child: ConstrainedBox(
          constraints: const BoxConstraints(
            minWidth: 100,
            minHeight: 100,
            maxWidth: 200,
            maxHeight: 200,
          ),
          child: Container(
            color: Colors.amber,
            width: 10,
            height: 10,
          ),
        ),
      ),
    ),
  );
}

这时候 尺寸强制被设置为了 100 * 100

Flutter基础 — Flutter基础特性插图(29)

查看约束情况

Flutter基础 — Flutter基础特性插图(30)

5.2 紧约束定义

它的最大/最小宽度是一致的,高度也一样

通过 BoxConstraints.tight 可以设置紧约束

void main() {
  runApp(build());
}

Widget build() {
  return MaterialApp(
    home: Scaffold(
      body: Center(
        child: ConstrainedBox(
          constraints: BoxConstraints.tight(const Size(100, 100)),
          child: Container(
            color: Colors.amber,
            width: 10,
            height: 10,
          ),
        ),
      ),
    ),
  );
}

Flutter基础 — Flutter基础特性插图(31)

宽高约束都被设置成了 100

Flutter基础 — Flutter基础特性插图(32)

6. 无边界 unbounded

6.1 UnconstrainedBox 不受约束

UnconstrainedBox 包裹内部的 Container 10*10 可以不受约束自己控制大小

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ConstrainedBox(
          constraints: const BoxConstraints(
            minWidth: 100,
            minHeight: 100,
            maxWidth: 300,
            maxHeight: 300,
          ),
          child: UnconstrainedBox(
            child: Container(
              width: 10,
              height: 10,
              color: Colors.blue,
            ),
          ),
        ),
      ),
      debugShowCheckedModeBanner: false,
    );
  }
}

显示了一个 10*10 的正方形,没有收到 ConstrainedBox 的影响

Flutter基础 — Flutter基础特性插图(33)

约束查看 Container 10*10,父级约束 最小宽高 100

Flutter基础 — Flutter基础特性插图(34)

6.2 unbounded 组件

RowColumnListView 这种组件 属于 unbounded

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: const [
            FlutterLogo(size: 50),
            FlutterLogo(size: 20),
            // Container(
            //   height: 2000,
            //   color: Colors.amber,
            // ),
          ],
        ),
      ),
      debugShowCheckedModeBanner: false,
    );
  }
}

Flutter基础 — Flutter基础特性插图(35)

Column 垂直元素 unconstrained 没有约束,高度不限制

Flutter基础 — Flutter基础特性插图(36)

加入一个高度超出屏幕区域的 Container

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: [
            const FlutterLogo(size: 50),
            const FlutterLogo(size: 20),
            Container(
              height: 2000, // 设置了 2000 高
              color: Colors.amber,
            ),
          ],
        ),
      ),
      debugShowCheckedModeBanner: false,
    );
  }
}

提示底部超出溢出

Flutter基础 — Flutter基础特性插图(37)

  • 清楚的显示了你溢出的情况,屏幕高 430 ,Column 被撑开 2070 , Container 高 2000 , 底部溢出高度 1640

Flutter基础 — Flutter基础特性插图(38)

7. 有状态无状态组件

在 Flutter 中,组件(也称为 Widget)分为有状态(StatefulWidget)和无状态(StatelessWidget)两种类型。这两者的区别在于是否需要保存和管理状态

无状态组件(StatelessWidget)

无状态组件是一种在应用运行过程中不会改变的组件。它们的属性是不可变的(immutable),这意味着一旦创建,它的显示内容就不会改变。StatelessWidget 的典型例子包括文本、图标或静态图片等简单的 UI 元素

特点:

  • 不会随着时间或用户交互而改变
  • 不包含内部状态
  • 适用于静态内容的场景

有状态组件(StatefulWidget)

有状态组件是一种在应用运行过程中可以改变的组件。它们需要管理自己的状态,并通过 State 类来控制该状态的变化。StatefulWidget 可以用于需要更新 UI 的场景,比如用户交互、动画或实时数据展示。

特点:

  • 可以动态改变内容。
  • 包含内部状态。
  • 适用于动态内容的场景。

7.1 无状态 StatelessWidget

准备两张图片

const img1 =
    "http://ducafecat.tech/2021/12/09/blog/2021-jetbrains-fleet-vs-vscode/2021-12-09-10-30-00.png";
const img2 =
    "http://ducafecat.tech/2021/12/09/blog/2021-jetbrains-fleet-vs-vscode/2021-12-09-20-45-02.png";

编写图片显示组件 BannerWidget

class BannerWidget extends StatelessWidget {
  const BannerWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Image.network(img1);
  }
}

MyApp 执行

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: const [
            Text('有无状态组件'),
            BannerWidget(),
          ],
        ),
      ),
      debugShowCheckedModeBanner: false,
    );
  }
}

运行

Flutter基础 — Flutter基础特性插图(39)

7.2 有状态 StatefulWidget

改写成有状态组件

class BannerWidget extends StatefulWidget {
  const BannerWidget({Key? key}) : super(key: key);

  @override
  State createState() => _BannerWidgetState();
}

class _BannerWidgetState extends State {
  String? imgUrl;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: () {
            setState(() {
              imgUrl = imgUrl == img1 ? img2 : img1;
            });
          },
          child: const Text("切换图片"),
        ),
        Image.network(imgUrl ?? img1),
      ],
    );
  }
}

运行

Flutter基础 — Flutter基础特性插图(40)

可以发现通过 setState 来管理和维护内部数据状态

7.3 有状态包裹无状态组件

编写图片显示组件

class ImageWidget extends StatelessWidget {
  const ImageWidget({Key? key, required this.imgUrl}) : super(key: key);

  final String imgUrl;

  @override
  Widget build(BuildContext context) {
    return Container(
        padding: const EdgeInsets.all(10),
        color: Colors.amber,
        child: Image.network(imgUrl));
  }
}

这里加了个 Container 显示边框

直接调用

      children: [
        ...
        ImageWidget(
          imgUrl: imgUrl ?? img1,
        ),
      ],

执行

Flutter基础 — Flutter基础特性插图(41)

可以发现很多组件都是无状态的,文本、图片、输入框、按钮、卡片、图标…

组件树

Flutter基础 — Flutter基础特性插图(42)

7.4 使用函数编写组件

编写函数组件

Widget imageWidget({required String imgUrl}) {
  return Container(
    padding: const EdgeInsets.all(10),
    color: Colors.amber,
    child: Image.network(imgUrl),
  );
}

调用

...
imageWidget(
          imgUrl: imgUrl ?? img1,
        ),

查看组件树

Flutter基础 — Flutter基础特性插图(43)

可以发现没有显示组件的名称 imageWidget 只是Container

Flutter 这样做是出于性能考虑,所以如果你是可复用组件,需要用 class 包裹

参考文献

Flutter Stateless and Stateful Widget

Flutter: Stateful vs Stateless Widget

8. 生命周期

Flutter 的生命周期主要针对的是组件(即 Widget)的生命周期

8.1 StatefulWidget 生命周期

Flutter基础 — Flutter基础特性插图(44)

执行顺序,从上往下

Flutter基础 — Flutter基础特性插图(45)

不要再 build 里面更新状态, 影响性能

initState 初始状态数据

  @override
  void initState() {
    super.initState();
    print("initState");
  }

build 渲染视图,可多次

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: () {
          },
          child: const Text("切换图片"),
        ),
        imageWidget(
          imgUrl: imgUrl ?? img1,
        ),
      ],
    );
  }

mounted 状态

flutter 分配完你的组件树位置,会设置 mounted 为 true

你需要在 mounted == true 情况下,调用 setState() 来更新 UI ,这才是安全的操作

  ElevatedButton(
    onPressed: () {
      if (mounted == true) {
        setState(() {
          imgUrl = imgUrl == img1 ? img2 : img1;
        });
      }
    },
    child: const Text("切换图片"),
  ),

didChangeDependencies

父或祖先widget中的InheritedWidget改变时会被调用

  // 父或祖先widget中的InheritedWidget改变时会被调用
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("didChangeDependencies");
  }

didUpdateWidget

父类 setState 后,子类就会触发

  // 父类 setState 后,子类就会触发
  @override
  void didUpdateWidget(oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget");
  }

addPostFrameCallback

渲染结束回调,只执行1次

如我们可以放在 initState 时设置

  // 初始 State, mounted 等于 true, 只执行1次
  @override
  void initState() {
    super.initState();
    print("initState");

    // 渲染结束调用,只执行1次
    SchedulerBinding.instance?.addPostFrameCallback((timeStamp) {
      print("addPostFrameCallback");
      print(timeStamp);
    });
  }

deactivate

从组件树中移除 State 时调用

  @override
  void deactivate() {
    super.deactivate();
    print("deactivate");
  }

dispose

组件被释放时调用

  @override
  void dispose() {
    print("dispose");
    super.dispose();
  }

代码

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

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

const img1 =
    "http://ducafecat.tech/2021/12/09/blog/2021-jetbrains-fleet-vs-vscode/2021-12-09-10-30-00.png";
const img2 =
    "http://ducafecat.tech/2021/12/09/blog/2021-jetbrains-fleet-vs-vscode/2021-12-09-20-45-02.png";

Widget imageWidget({required String imgUrl}) {
  return Container(
    padding: const EdgeInsets.all(10),
    color: Colors.amber,
    child: Image.network(imgUrl),
  );
}

class BannerWidget extends StatefulWidget {
  const BannerWidget({Key? key}) : super(key: key);

  // 创建 State 只执行1次
  @override
  State createState() {
    print("createState");
    return _BannerWidgetState();
  }
}

class _BannerWidgetState extends State {
  String? imgUrl;

  // 初始 State, mounted 等于 true, 只执行1次
  @override
  void initState() {
    super.initState();
    print("initState");

    // 渲染结束调用,只执行1次
    SchedulerBinding.instance?.addPostFrameCallback((timeStamp) {
      print("addPostFrameCallback");
      print(timeStamp);
    });
  }

  // 父或祖先widget中的InheritedWidget改变时会被调用
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("didChangeDependencies");
  }

  // 父类 setState 后,子类就会触发
  @override
  void didUpdateWidget(oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget");
  }

  // 从组件树中移除 State 时调用
  @override
  void deactivate() {
    super.deactivate();
    print("deactivate");
  }

  // 组件被释放时调用
  @override
  void dispose() {
    print("dispose");
    super.dispose();
  }

  // UI 被重新渲染的时候多次执行
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: () {
            if (mounted == true) {
              setState(() {
                imgUrl = imgUrl == img1 ? img2 : img1;
              });
            }
          },
          child: const Text("切换图片"),
        ),
        imageWidget(
          imgUrl: imgUrl ?? img1,
        ),
      ],
    );
  }
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: const [
            Text('有无状态组件'),
            BannerWidget(),
          ],
        ),
      ),
      debugShowCheckedModeBanner: false,
    );
  }
}

输出

flutter: createState
flutter: initState
flutter: didChangeDependencies
flutter: addPostFrameCallback
flutter: 0:00:00.000000

8.2 StatelessWidget 生命周期

无状态组件,不需要处理生命周期,直接显示即可

abstract class StatelessWidget extends Widget {
  /// Initializes [key] for subclasses.
  const StatelessWidget({ Key? key }) : super(key: key);

  /// Creates a [StatelessElement] to manage this widget's location in the tree.
  ///
  /// It is uncommon for subclasses to override this method.
  @override
  StatelessElement createElement() => StatelessElement(this);

在源码中可见 createElement() 创建组件到组件树,不需要重写去维护

8.3 App生命周期

第一步: 创建 StatefulWidget 组件,混入 WidgetsBindingObserver

class _MyAppState extends State with WidgetsBindingObserver {
  ...

第二步:添加观察者 addObserver

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance?.addObserver(this); //添加观察者
  }

生命周期变化时回调 didChangeAppLifecycleState

  //  生命周期变化时回调
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    print("didChangeAppLifecycleState: $state");
  }

Flutter基础 — Flutter基础特性插图(46)

代码

import "package:flutter/material.dart";

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

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

//实现WidgetsBindingObserver观察者
class _MyAppState extends State with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance?.addObserver(this); //添加观察者
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text("App生命周期"),
        ),
        body: Column(
          children: [
            const Text("首页"),
          ],
        ),
      ),
    );
  }

  //  生命周期变化时回调
  //  resumed:应用可见并可响应用户操作,app进入前台
  //  inactive:用户可见,但不可响应用户操作,比如来了个电话,前后台切换的过渡状态
  //  paused:已经暂停了,用户不可见、不可操作,app进入后台
  //  suspending:应用被挂起,此状态IOS永远不会回调
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    print("didChangeAppLifecycleState: $state");
  }

  //当前系统改变了一些访问性活动的回调
  @override
  void didChangeAccessibilityFeatures() {
    super.didChangeAccessibilityFeatures();
    print("didChangeAccessibilityFeatures");
  }

  //低内存回调
  @override
  void didHaveMemoryPressure() {
    super.didHaveMemoryPressure();
    print("didHaveMemoryPressure");
  }

  //用户本地设置变化时调用,如系统语言改变
  @override
  void didChangeLocales(List? locale) {
    super.didChangeLocales(locale);
    print("didChangeLocales");
  }

  //应用尺寸改变时回调,例如旋转
  @override
  void didChangeMetrics() {
    super.didChangeMetrics();
    Size? size = WidgetsBinding.instance?.window.physicalSize;
    print("didChangeMetrics  :宽:${size?.width} 高:${size?.height}");
  }

  //系统切换主题时回调
  @override
  void didChangePlatformBrightness() {
    super.didChangePlatformBrightness();
    print("didChangePlatformBrightness");
  }

  ///文字系数变化
  @override
  void didChangeTextScaleFactor() {
    super.didChangeTextScaleFactor();
    print(
        "didChangeTextScaleFactor  :${WidgetsBinding.instance?.window.textScaleFactor}");
  }

  @override
  void dispose() {
    super.dispose();
    WidgetsBinding.instance?.removeObserver(this); //销毁观察者
  }
}

输出信息

flutter: didChangeMetrics  :宽:1125.0 高:2436.0
flutter: didChangeAppLifecycleState: AppLifecycleState.inactive
flutter: didHaveMemoryPressure
flutter: didChangeAppLifecycleState: AppLifecycleState.paused
flutter: didChangePlatformBrightness
flutter: didChangeMetrics  :宽:1125.0 高:2436.0
flutter: didChangePlatformBrightness
flutter: didChangeMetrics  :宽:1125.0 高:2436.0
flutter: didChangeAppLifecycleState: AppLifecycleState.inactive
flutter: didChangeAppLifecycleState: AppLifecycleState.resumed

创作不易,希望读者三连支持 💖
赠人玫瑰,手有余香 💖

本站无任何商业行为
个人在线分享 » Flutter基础 — Flutter基础特性
E-->