Flutter - StatefulWidget (有状态的 Widget) 和 生命周期

news/2025/2/25 7:47:52

StatefulWidget 

/**
 * 需求:
 * 两个按钮,一个计数器
 * 这里要用到 StatefulWidget,因为 StatelessWidget 通常用来展示固定不变的数据
 */
main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomeContent(),
    );
  }
}

/**
 * Widget 中的数据都是不可变的,为何必须定义为 final ?
 * 因为 Widget 中展示的数据发生变化时辉重新构建整个 Widget
 * Widget 源码中有 @immutable 注解,(被@immutable注解标明的类或者子类都必须是不可变的)
 *
 * Flutter 将 StatefulWidget 设计成了两个类,创建 StatefulWidget 时必须创建两个类:
 * 1 一个类继承自 StatefulWidget,作为 Widget树的一部分
 * 2 一个类继承自 State,用于记录 StatefulWidget 会变化的状态,并且根据状态的变化,构建出新的 Widget
 */
class MyHomeContent extends StatefulWidget {

  @override
  State<MyHomeContent> createState() => _MyHomeContentState();
}

class _MyHomeContentState extends State<MyHomeContent> {

  var num = 0;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            '计数:$num',
            style: TextStyle(fontSize: 28,color: Colors.blue,decoration: TextDecoration.none)
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(onPressed: (){
                setState(() {
                  num++;
                });
              }, child: Icon(Icons.add)),
              ElevatedButton(onPressed: (){
                setState(() {
                  num--;
                });
              }, child: Icon(Icons.remove))
            ],
          )
        ],
      ),
    );
  }
}

生命周期

main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyStatefulWidget(),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {

  MyHomeContent(){
    print('生命周期 ---- MyStatefulWidget的构造方法');
  }

  /**
   * 当 Flutter 构建一个 StatefulWidget 时,会立即调用 createState() 方法。
   * 这个方法返回一个 State 对象,该对象将管理这个 Widget 的状态。
   */
  @override
  State<MyStatefulWidget> createState() => _MyNumState();
}

class _MyNumState extends State<MyStatefulWidget> {

  _MyNumState(){
    print('生命周期 ---- _MyNumState的构造方法');
  }

  /**
   * initState() 是 State 对象的初始化方法,只会被调用一次。
   * 通常在这里进行一些初始化操作,比如订阅流、初始化数据等。
   */
  @override
  void initState() {
    super.initState();
    print('生命周期 ---- _MyNumState的 init方法');
  }

  /**
   * didChangeDependencies() 在 initState() 之后立即调用,
   * 并且在依赖的 InheritedWidget 发生变化时也会调用。
   * 通常在这里执行一些依赖于 BuildContext 或 InheritedWidget 的操作。
   */
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print('生命周期 ---- _MyNumState的 didChangeDependencies方法');
  }

  /**
   * build() 方法是构建 Widget 树的核心方法,每次 UI 需要更新时都会调用。
   * 这个方法必须返回一个 Widget,通常是组合其他 Widget 来构建界面。
   */
  @override
  Widget build(BuildContext context) {
    print('生命周期 ---- _MyNumState的 build方法');
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Row(
            children: [
              ElevatedButton(onPressed: (){
                /**
                 * setState() 用于通知 Flutter 框架状态已经改变,需要重新构建 UI。
                 * 调用 setState() 会触发 build() 方法。
                 */
                setState(() {
                  
                });
              }, child: Icon(Icons.remove))
            ],
          )
        ],
      ),
    );
  }

  /**
   * 当父 Widget 重建并传入新的 Widget 配置时,didUpdateWidget() 会被调用。
   * 通常在这里比较新旧 Widget 的配置,并根据需要更新状态。
   */
  @override
  void didUpdateWidget(covariant MyStatefulWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    print('生命周期 ---- _MyNumState的 didUpdateWidget方法');
  }

  /**
   * 当 State 对象从 Widget 树中移除时,deactivate() 会被调用。
   * 通常在这里做一些清理工作,但 State 对象仍然可能被重新插入到树中。
   */
  @override
  void deactivate() {
    super.deactivate();
    print('生命周期 ---- _MyNumState的 deactivate方法');
  }

  /**
   * 当 State 对象从 Widget 树中永久移除时,dispose() 会被调用。
   * 通常在这里释放资源,比如取消订阅、关闭流等。
   */
  @override
  void dispose() {
    super.dispose();
    print('生命周期 ---- _MyNumState的 dispose方法');
  }
  
}

 


http://www.niftyadmin.cn/n/5865200.html

相关文章

Django ORM 的常用字段类型、外键关联的跨表引用技巧,以及 `_` 和 `__` 的使用场景

一、Django ORM 常用字段类型 1. 基础字段类型 字段类型说明示例CharField字符串字段&#xff0c;必须指定 max_lengthname models.CharField(max_length50)IntegerField整数字段age models.IntegerField()BooleanField布尔值字段is_active models.BooleanField()DateFiel…

【入门音视频】音视频基础知识

&#x1f308;前言&#x1f308; 这个系列在我学习过程中&#xff0c;对音视频知识归纳总结的笔记。因为音视频相关讲解非常稀少&#xff0c;所以我希望通过这个音视频系列&#xff0c;跟大家一起学习音视频&#xff0c;希望减少初学者在学习上的压力。同时希望也欢迎指出文章的…

【C++11】 并发⽀持库

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;C从入门到精通 目录 前言&#xff1a;&#x1f680; 并发⽀持库一&#xff1a;&#x1f525; thread库 二&#xff1a;&#x1f525; this_thread 三&#xff1a;&#x1f525; mutex 四&#xff1…

【Gin-Web】Bluebell社区项目梳理6:限流策略-漏桶与令牌桶

本文目录 一、限流二、漏桶三、令牌桶算法四、Gin框架中实现令牌桶限流 一、限流 限流又称为流量控制&#xff0c;也就是流控&#xff0c;通常是指限制到达系统的并发请求数。 限流虽然会影响部分用户的使用体验&#xff0c;但是能一定程度上保证系统的稳定性&#xff0c;不至…

从零开始用react + tailwindcs + express + mongodb实现一个聊天程序(二)

1.安装mogondb数据库 参考MongoDB安装配置教程&#xff08;详细版&#xff09;_mongodb安装详细步骤-CSDN博客 安装mondbcompass数据库连接工具 参考https://www.mongodb.com/zh-cn/docs/compass/current/connect/ 2.后端服务 1.创建src文件夹 并在src文件夹下创建 index…

DIP的实际举例

SOLID原则。 依赖倒置原则&#xff08;DIP&#xff09;的核心是高层模块不应该依赖于低层模块&#xff0c;二者都应该依赖于抽象&#xff08;接口或抽象类&#xff09; 例如&#xff0c;随着业务的发展&#xff0c;订单总金额的计算规则可能需要根据不同的客户类型或促销活动…

毕业离校管理系统的开发与需求分析

在当今信息化的时代背景下&#xff0c;高校的毕业生离校管理工作也逐渐向数字化转型。为了提高工作效率&#xff0c;减少人为错误&#xff0c;增强信息透明度&#xff0c;毕业离校管理系统应运而生。该系统旨在为学校提供一个高效、准确的毕业生离校管理平台&#xff0c;从而提…

python类型转换深浅拷贝

1.类型转换 1.1 int(x):转化为一个整数&#xff0c;只能转换由纯数字组成的字符串 float->int 浮点型强转整形会去掉小数点后面的数&#xff0c;只保留整数部分 a 1.2 print(type(a)) #<class float> b int(a) print(type(b)) #<class int>print(int…