Flutter 中的 StatefulWidget 基本使用

1,256 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

关于 StatefulWidget

StatefulWidget

在实际开发中,StatelessWidget 通常用来描述 UI 展示中状态固定的组件。如果 状态会发生改变,则需要使用 StatefulWidget 来描述

为什么 StatefulWidget 可以用来描述状态变化的组件?

源码展示

abstract class StatefulWidget extends Widget {
    const StatefulWidget({ Key? key }) : super(key: key);
    
    @override
    StatefulElement createElement() => StatefulElement(this);
    
    @protected
    @factory
    State createState();
}

StatefulWidget 继承自 Widget,Widget 是不可变的,所以 StatefulWidget 也不能定义状态。但是在 StatefulWidget 源码中可以发现,在 StatefulWidget 的初始化中,必须实现 createState() 这个方法,这个方法返回一个 State 对象,这个对象用于记录 StatefulWidget 会变化的状态,并且根据状态的变化,构建出新的 Widget

// 定义 StatefulWidget 子类
class HomeContent extends StatefulWidget {
    const HomeContent({Key? key}) : super(key: key);
    
    // 重写 createState 方法
    @override
    State<StatefulWidget> createState() {
      
      // 创建 State 对象并返回
      return _HomeContentState();
    }
}

// 定义 State 子类 
class _HomeContentState extends State<StatefulWidget> {
    @override
    Widget build(BuildContext context) {
      // 构建自己的 Widget
      return const Text("dart");
    }
}

为什么 StatefulWidgetbuild() 方法放在 State

在构建 Widget 树时,会获取 State 的对象,并且该对象会调用 build() 方法去获取 StatefulWidget 希望构建的 Widget。在 Flutter 运行过程中,Widget 会被不断的创建和销毁,在状态改变时,State 并不会重新被创建,只是将需要保存的状态保存在 HomeContentState 中


示例展示

需求:通过 StatefulWidget 实现一个计数器

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

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

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("计算器"),
      ),
      body: const HomeContent(),
    );
  }
}

class HomeContent extends StatefulWidget {
  const HomeContent({Key? key}) : super(key: key);
  @override
  State<StatefulWidget> createState() {
    return _HomeContentState();
  }
}

class _HomeContentState extends State<StatefulWidget> {

  int _value = 0;

  @override
  Widget build(BuildContext context) {
    return Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            _getRowButtons(),
            Text("结果是: $_value",style: const TextStyle(fontSize: 30))
          ],
        )
    );
  }

  Widget _getRowButtons () {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        ElevatedButton(
            onPressed: (){
              
              _value++;
              
              // 调用 setState 刷新状态 
              setState(() {
                    // 写在外面和里面是一样的,如果写在里面,在源码中 setState 也会调用该回调方法
                    //_value++;
              });
            },
            style: ElevatedButton.styleFrom(primary: Colors.orange),
            child: const Text("+",style: TextStyle(fontSize: 20))
        ),
        ElevatedButton(
            onPressed: (){
              _value--;
              setState(() {

              });
            },
            style: ElevatedButton.styleFrom(primary: Colors.red),
            child: const Text("-",style: TextStyle(fontSize: 20))
        )
      ],
    );
    
  }
}

示例效果

未命名.gif