StreamBuilder 可以在构建方法之外吗?

Can a StreamBuilder be outside the build method?

我找不到任何关于 StreamBuilder 需要在代码中的什么位置的信息,所以我在这里问。

我的 flutter 应用程序中有一个屏幕,其中有很多输入文本字段。每个文本框都有这样的代码结构:

TextField(
                  keyboardType: TextInputType.text,
                  controller: clientLNameController,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    trxnProvider.changeclientLName(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Client Last Name',
                      labelText: 'Client Last Name'),
                ),

在 initState() 函数中,我调用了一个从 Firestore 集合中提取数据并填充与每个文本字段关联的 TextEditingController 的方法。

@override
  void initState() {
    getTrxn();
  }

正是在这个函数中,我尝试使用 StreamBuilder 获取数据。这是代码。

getTrxn() async {
    StreamBuilder (
        stream: _db.collection('agency').doc(globals.agencyId).
        collection('trxns').doc(globals.currentTrxnId).snapshots(),
        builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
          if (trxnSnapshot.hasData) {
            clientFNameController.text = trxnSnapshot.data['clientFName'] ?? "";
          }
    )
    return SizedBox.shrink();
}

我遇到的问题是,当我通过调试器 运行 代码并尝试单步执行代码时,我到达了 StreamBuilder 行,然后我退出了函数。 None StreamBuilder 中的代码被执行但也没有错误。

我在想我不能在“构建”功能之外使用 StreamBuilder。

@override
  Widget build(BuildContext context) {

这是正确的还是我遗漏了什么?

这样做

  late final StreamSubscription myStream;

  @override
  void initState() {
    myStream = _db
        .collection('agency')
        .doc(globals.agencyId)
        .snapshots()
        .listen((snapshot) => clientFNameController.text = snapshot.data()?['clientFName'] ?? "");
    super.initState();
  }

确保在完成后处理流

  @override
  void dispose() {
    myStream.cancel();
    super.dispose();
  }

一次性表达式

假设您有一个 Printer class,您可以在其中显示消息并在显示消息时执行某些操作:

class Printer {
  final void Function(String) callback;
  
  const Printer({required this.callback});
  
  void show(String message) {
    print(message);
    callback(message);
  }
}

现在,让我们使用它:

void main() {
  Printer(callback: (message) {
    print("Message $message was printed.");
  });
}

如果您 运行 此代码,则不会发生任何事情,因为您没有调用 show 方法。上面是我称之为 throwaway expression 的示例,因为除了 Dart 创建一个 object 并从内存中清除它之外,什么都没有发生。

下面的代码片段可以工作:

void main() {
  Printer(callback: (message) {
    print("Message '$message' was printed.");
  }).show("Hello, world!");
}

这将输出

Hello, world!
Message 'Hello, world!' was printed.

build方法

通常,当您通过创建 MaterialApp 启动 Flutter 应用程序时,Flutter 会查看其 home 参数(这是一个 Widget)并调用其 build 方法。此小部件将遍历其 build 方法中声明的所有 children,并将调用它们的 build 方法。重复此过程,直到不再有 children.

当调用Widget 的build 方法时,会执行一些逻辑。因此,如果你在 build 方法之外放置一个 Widget A,A 的逻辑将不会被执行(除非你显式地调用 A 的 build 方法,但为此你需要一个 BuildContext)并且它将是一个 一次性表达式 。所以你说得对

None of the code inside the StreamBuilder gets executed but there is no error either.

解决方案

  1. 将您的 StreamBuilder 放入您的 build 方法中。

  2. .