setState 是否为 flutter 中的屏幕重建整个 widget 树,它与其他 State 管理相比如何

Does setState rebuild the whole widget tree for a screen in flutter and how does it compare with other State management

我有点困惑,我最近一直在研究 flutter 的状态管理,我想知道如果将自定义有状态小部件放置在无状态小部件中会发生什么,假设 widgetA(父级)是无状态小部件并且它有一个子 WidgetB,它是一个有状态的小部件,另一个子 WidgetC 是一个无状态的小部件。

现在我的问题是:

如果您有可以帮助我理解的外部链接或资源,请提供它们

如果我说错了,请大家指正。

按顺序回答您的问题:

  1. 如果你在 WidgetB 上调用 setState() 它会重建自己和它的后代,无论它们是 Stateless 还是 Stateful 小部件.

  2. 使用 BLoC 方法,大多数时候可以选择使用 Stateful WidgetssetState() 来管理状态。在这种方法中,您将使用 UI 中的 events,它将在您的 BLoC 中转换为 'States'。这个状态将被传递到一个流中。您的 UI 每次在他们正在收听的 Stream 上收听新值时都会使用 StreamBuilders 重建自身。这将触发 StreamBuilder 重建自身及其后代。

  3. 如果您使用 BLoCProvider + Streams,我建议避免使用 setState()StatefulWidgets,也许除了 UI 之类的一些例外,例如。动画。

  4. BLoC 是一种与 Provider package 相得益彰的设计方法。 BLoC package 甚至在内部使用 Provider

P.S.: 而 BLoC 是一种架构模式,用于管理应用程序的数据和状态。 Provider 是 'just' Inherited Widgets 的包装器,它有助于在整个 Widget 树中公开数据,而不是架构模式。

使用 provider 包管理状态的架构模式解决方案的其他示例是 MobX

setState() 将调用 build() 方法并使用小部件树重建(在引擎盖下使用 Flutter 优化),如果您只想构建一部分,则有一个替代方案:创建一个 Provider 来保存更改你想反映在 UI 中,并用消费者包装那个小部件 - 当你从提供者调用 notifyListener() 时,只有那个小部件将重建。

例如:

 child: Consumer<MessageIconStateProvider>(
        builder: (context, messageIconProvider, child) {
          return Container(
            height: 40,
            child: messageIconProvider.isShowMessageIcon
                ? Icon(
              Icons.send,
              size: 24,
              color: Colors.white,
            )
                : Icon(
              Icons.mic_outlined,
              size: 24,
              color: Colors.white,
            ),
          );
        }
    )

提供商:

 import 'package:flutter/material.dart';

class MessageIconStateProvider with ChangeNotifier {
  var isShowMessageIcon = true;
  
  void setIconToMessage(bool setIconToMessage){
    if(setIconToMessage != isShowMessageIcon) {
      isShowMessageIcon = setIconToMessage;
      notifyListeners();
    }
  }


}

并且不要忘记在您的 main.dart 文件中定义它:

    class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => MessageIconStateProvider()),
      ],...