[Flutter][基本应用][Widget] StatelessWidget和StatefulWidget的差异

78 阅读2分钟

概要

本文就Flutter两种Widget,StatelessWidget和StatefulWidget的差异进行对比。 StatelessWidget 是无状态组件、StatelessWidget是有状态组件。

StatelessWidget

StatelessWidge(无状态组件)是指在创建后不可改变状态的widget。它只接受外部传入的数据(即props),并根据这些数据来渲染UI界面。statelessWidge一旦创建,就不会再发生变化,因此它的生命周期非常简单,只有一个build()方法,用于构建UI。

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

  @override
  StatelessElement createElement() => StatelessElement(this);

  @protected
  Widget build(BuildContext context);
}

StatefulWidget

StatefulWidget(有状态组件)是指在创建后可以改变状态的widget。除了接受外部传入的数据(即props),它还可以在内部维护一个状态对象,用于保存需要动态变化的数据。当状态发生变化时,StatefulWidget会重新调用build()方法来更新UI。StatefulWidget的生命周期包括以下几个阶段

  • createState():创建State对象,该对象存储了widget的可变状态。
  • initState():在State对象被插入widget树时调用,用于初始化状态。
  • didChangeDependencies():在State对象依赖的一些数据发生变化时调用。
  • build():用于构建UI界面。
  • didUpdateWidget():在widget配置发生变化,需要更新时调用。
  • deactivate():当widget被移除时调用。
  • dispose():在widget被永久移除时调用,用于释放资源。 总的来说,statelessWidge适用于那些不需要改变状态的简单UI组件,而StatefulWidget适用于那些需要根据状态动态变化的复杂UI组件。
abstract class StatefulWidget extends Widget {
  const StatefulWidget({ super.key });

  StatefulElement createElement() => StatefulElement(this);

  State createState();
}

State

abstract class State<T extends StatefulWidget> with Diagnosticable {

T get widget => _widget!;
T? _widget;


_StateLifecycle _debugLifecycleState = _StateLifecycle.created;

_StateLifecycle _debugLifecycleState = _StateLifecycle.created;

bool _debugTypesAreRight(Widget widget) => widget is T;

BuildContext get context {
  assert(() {
    if (_element == null) {
      throw FlutterError(
        'This widget has been unmounted, so the State no longer has a context (and should be considered defunct). \n'
        'Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.',
      );
    }
    return true;
  }());
  return _element!;
}
StatefulElement? _element;


bool get mounted => _element != null;

void initState() {
  assert(_debugLifecycleState == _StateLifecycle.created);
  if (kFlutterMemoryAllocationsEnabled) {
    MemoryAllocations.instance.dispatchObjectCreated(
      library: _flutterWidgetsLibrary,
      className: '$State',
      object: this,
    );
  }
}

void didUpdateWidget(covariant T oldWidget) { }

void reassemble() { }

void setState(VoidCallback fn) {

//此处略去若干代码

//标记元素为脏,需要重新绘制
_element!.markNeedsBuild();

}


void deactivate() { }


void activate() { }


void dispose() {
  assert(_debugLifecycleState == _StateLifecycle.ready);
  assert(() {
    _debugLifecycleState = _StateLifecycle.defunct;
    return true;
  }());
  if (kFlutterMemoryAllocationsEnabled) {
    MemoryAllocations.instance.dispatchObjectDisposed(object: this);
  }
}


Widget build(BuildContext context);


void didChangeDependencies() { }



void debugFillProperties(DiagnosticPropertiesBuilder properties) {
  super.debugFillProperties(properties);
  assert(() {
    properties.add(EnumProperty<_StateLifecycle>('lifecycle state', _debugLifecycleState, defaultValue: _StateLifecycle.ready));
    return true;
  }());
  properties.add(ObjectFlagProperty<T>('_widget', _widget, ifNull: 'no widget'));
  properties.add(ObjectFlagProperty<StatefulElement>('_element', _element, ifNull: 'not mounted'));
}

示例代码

class MyStatelessWidget extends StatelessWidget {
  final String text;
  const MyStatelessWidget({Key key, this.text}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text(text),
    );
  }
}
import 'package:flutter/material.dart';
class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int counter = 0;
  void incrementCounter() {
    setState(() {
      counter++;
    });
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          Text('Counter: $counter'),
          RaisedButton(
            onPressed: incrementCounter,
            child: Text('Increment'),
          ),
        ],
      ),
    );
  }
}