美文网首页
Flutter:StatefulWidget 的状态管理与生命周

Flutter:StatefulWidget 的状态管理与生命周

作者: 时光啊混蛋_97boy | 来源:发表于2023-01-30 15:37 被阅读0次

原创:有趣知识点摸索型文章
创作不易,请珍惜,之后会持续更新,不断完善
个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的IOS成长历程,希望能与大家一起进步
温馨提示:由于简书不支持目录跳转,大家可通过command + F 输入目录标题后迅速寻找到你所需要的内容

目录

  • 一、StatefulWidget 的状态管理
  • 二、Flutter 默认 Demo 对 StatefulWidget 的使用
  • 三、StatefulWidget 的生命周期

一、StatefulWidget 的状态管理

StatefulWidgetStatelessWidget 均继承自 Widget

abstract class StatefulWidget extends Widget
abstract class StatelessWidget extends Widget

Widget上方有个注解:@immutable。该注解的意思就是不可变的意思,作用就是让 widget 及其子类是不可变的,定义的变量必须是 final 的,所以,这就导致无法在 StatelessWidget 内实现数据更新操作。

@immutable
abstract class Widget extends DiagnosticableTree

StatefulWidget 是相对于 StatelessWidget 实现可变的 widget。由于 StatefulWidget 也是继承于 widget,所以自然在 widget 内是做不了变量更新的。既然 Widget 是不可变,那么 StatefulWidget 如何来存储可变的状态呢?

StatelessWidget 无所谓,因为它里面的数据通常是直接定义完后就不修改的。但 StatefulWidget 需要有状态(可以理解成变量)的改变,这如何做到呢?

FlutterStatefulWidget 设计成了两个类,也就是你创建 StatefulWidget 时必须创建两个类:一个类继承自 StatefulWidget,作为 Widget 树的一部分;另外一个类继承自 State,用于记录 StatefulWidget 会变化的状态,并且根据状态的变化,构建出新的 Widget

基本结构如下:

class MyStatefulWidget extends StatefulWidget {
  @override
  State< MyStatefulWidget > createState() {
    // 将创建的State返回
    return MyState();
  }
}
class MyState extends State<MyStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return <构建自己的Widget>;
  }
}

二、Flutter 默认 Demo 对 StatefulWidget 的使用

我们来看看系统为我们默认生成的页面中对 StatefulWidget 的使用。

这里有一个属性 title 表示的是页面的标题,其值由创建 MyHomePage 处赋予,在 Statebuild 方法中进行使用。像这样的属性,我们总是将其标记为 finalconst MyHomePage({ })表示其初始方法,需要传入父类的属性和当前类中自定义的属性。

class MyHomePage extends StatefulWidget {
  final String title;
  const MyHomePage({super.key, required this.title});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

而其对应的继承自 State,用于记录 StatefulWidget 变化状态的类如下:

class _MyHomePageState extends State<MyHomePage> {

}

在其中我们新增加了一个变量 _counter,其初值为0,每当点击 + 按钮调用一次 _incrementCounter 方法就会让其值增加1。由于其值的改变是在 setState 中进行的,而当在 setState 中的值发生改变的时候,就会告诉 Flutter 框架当前状态发生了改变,这将导致它重新运行下面的构建方法 build。如果我们改变 _counter 却不调用 setState(),那么构建方法 build 将不会被再次调用,看起来什么都不会发生。

int _counter = 0;

void _incrementCounter() {
  setState(() {
    _counter++;
  });
}

每次调用 setState 时都会重新运行下面这个方法。此处我们从 MyHomePage 对象中获取值,并使用它来设置我们的应用栏标题。

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text(widget.title),
    ),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          const Text(
            'You have pushed the button this many times:',
          ),
          Text(
            '$_counter',
            style: Theme.of(context).textTheme.headline4,
          ),
        ],
      ),
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: _incrementCounter,
      tooltip: 'Increment',
      child: const Icon(Icons.add),
    ),
  );
}

MyHomePage 对象是在 MyAppbuild 方法中进行创建的。MyApp这个组件是我们应用程序的根组件。

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

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

在入口方法 main 方法中,系统调用了 runApp 方法,将 MyApp对象作为参数进入了传入。

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

总结 Flutter 自定义 StatefulWidget 的套路:

  • 快捷代码模块:输入stlessstful 系统就会自动补全代码
  • 自定义 Widget:继承自 StatefulWidget,重载 createState 方法来加载自定义的 state
  • 自定义 State:继承自 State,实现你真正的 UI 部分和状态(Data)管理。自定义的 State 做状态管理,而 setState 做状态更新(更新完会触发 Widget 重新进行 build)。

三、StatefulWidget 的生命周期

既然是个对象,就有生命流程。StatelessWidget 可以由父 Widget 直接传入值,调用 build 方法来构建,整个过程非常简单;而 StatefulWidget 需要通过 State 来管理其数据,并且还要监控状态的改变决定是否重新 build 整个 Widget,所以,我们主要讨论 StatefulWidget 的生命周期,也就是它从创建到销毁的整个过程。

1、StatefulWidget 类

class MyCounterWidget extends StatefulWidget {

}

执行 StatefulWidget 的构造函数(Constructor)来创建出 StatefulWidget

MyCounterWidget() {
  print("MyCounterWidget:执行了构造方法");
}

执行 StatefulWidgetcreateState 方法,来创建一个维护 StatefulWidgetState 对象

@override
State<StatefulWidget> createState() {
  print("MyCounterWidget:执行了 createState 方法");
  // 将创建的 State 返回
  return MyCounterState();
}

2、State 类

class MyCounterState extends State<MyCounterWidget> {

}

执行 State 类的构造方法(Constructor)来创建 State 对象。

MyCounterState() {
  print("MyCounterState:执行构造方法");
}

执行 initState。我们通常会在这个方法中执行一些数据初始化的操作,或者也可能会发送网络请求。

@override
void initState() {
  super.initState();
  print("MyCounterState:执行 init 方法");
}

注意这个方法是重写父类的方法,必须调用 super,因为父类中会进行一些其他操作。并且如果你阅读源码,你会发现这里有一个注解(annotation):@mustCallSuper

@protected
@mustCallSuper
void initState() {
  assert(_debugLifecycleState == _StateLifecycle.created);
}

执行 didChangeDependencies 方法,这个方法在两种情况下会调用。

  • 情况一:调用 initState 方法时会被调用
  • 情况二:从其他对象中依赖一些数据发生改变时,比如 InheritedWidget
@override
void didChangeDependencies() {
  super.didChangeDependencies();
  print("MyCounterState:执行 didChangeDependencies 方法");
}

Flutter 执行 build 方法,来看一下我们当前的 Widget 需要渲染哪些 Widget

@override
Widget build(BuildContext context) {
    print("MyCounterState:执行 build 方法");
    return Center( )
}

当前的 Widget 不再使用时,会调用 dispose 进行销毁。

@override
void dispose() {
  super.dispose();
  print("MyCounterState 执行 dispose 方法");
}

手动调用 setState 方法,会根据最新的状态(数据)来重新调用 build 方法,构建对应的 Widgets

setState(() {
  _counter++;
});

执行 didUpdateWidget 方法是在当父 Widget 触发重建(rebuild)时,系统会调用 didUpdateWidget 方法。

@override
void didUpdateWidget(MyCounterWidget oldWidget) {
  super.didUpdateWidget(oldWidget);
  print("MyCounterState:执行 didUpdateWidget 方法");
}

上面的代码直接运行,打印如下:

flutter: MyApp:build
flutter: MyCounterWidget:执行了构造方法
flutter: MyCounterWidget:执行了 createState 方法

flutter: MyCounterState:执行构造方法
flutter: MyCounterState:执行 init 方法
flutter: MyCounterState:执行 didChangeDependencies 方法
flutter: MyCounterState:执行 build 方法

注意这里 Flutterbuild 所有的组件两次。如果你是用 Android Studio 开发的话,会有这个问题,但是如果使用 VSCode 进行开发则是正常的,即只会调用一遍的,所以不用太在意,可以理解为是 Android StudioBug,其运行到手机上肯定是正常的。

flutter: MyApp:build
flutter: MyCounterWidget:执行了构造方法
flutter: MyCounterState:执行 didUpdateWidget 方法
flutter: MyCounterState:执行 build 方法

当我们改变状态,手动执行 setState 方法后会打印如下结果:

flutter: MyCounterState:执行 build 方法

相关文章

网友评论

      本文标题:Flutter:StatefulWidget 的状态管理与生命周

      本文链接:https://www.haomeiwen.com/subject/xtumhdtx.html