Skip to content

setState

调用一个StatefulWidget的setState方法,会触发Widget的build方法,然后重新build子Widget。所以,你一定会在状态组件中,使用setState方法。当然如果你的StatefulWidget并没有使用setState方法,那么你一定要在StatelessWidget和StatefulWidget中做出选择。

异步更新

有时候,如果不使用FutureBuilder,同样会遇到在异步函数中调用setState触发build来更新UI。一方面我们不能保证setState的执行顺序,另一方面我们也不能保证执行的过程中,组件不被销毁,所以我们要对setState进行优化。在更新前,使用mounted校验组件是否被销毁。使用下面的代码,覆盖默认的setState方法,这样一来当组件被销毁时,放弃执行setState方法。这样也是短路逻辑之一。如果不这样做,运行的过程中,你也会看到不必要的报错。

dart
@override
void setState(fn) {
  if (!mounted) {
    return;
  }
  super.setState(fn);
}

将StatefulWidget构造成下面的组件

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

class MyWidget extends StatefulWidget {
  const MyWidget({super.key});

  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
 @override
  void setState(fn) {
    if (!mounted) {
      return;
    }
    super.setState(fn);
  }


  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}

避免循环

setState方法会触发build方法,所以,在build方法中,不应该调用setState方法。否则会导致渲染死循环

先计算,在setState

状态计算和刷新UI是两个不同的过程,应该分开执行,这样可以避免UI阻塞。在setState方法中,不应该直接修改状态,而是应该先计算状态,然后再调用setState方法。 对于占用较大的计算,使用async/await,或者使用compute。待计算完成后,在刷新UI。
不过由于回调函数是在完成计算后,才刷新UI,所以只有较大运算逻辑时,且不使用FutureBuilder,才需要这样做。 如果只是:

dart
setState(() {
  loaded = true;
});

之类的简单逻辑,则没有必要。

Statefulwidget 最小化单元

StatefulWidget应该尽量最小化。这样可以避免setState时,重绘过多的组件。

仅用于培训和测试,通过使用本站代码内容随之而来的风险与本站无关。版权所有,未经授权请勿转载,保留一切权利。
ICP备案号:滇ICP备15009214号-13   公安网备:滇公网安备 53312302000061号