简体   繁体   中英

Can a StreamBuilder be outside the build method?

I can't find any information on where the StreamBuilder needs to be within the code so I am asking here.

I have a screen in my flutter app that has a lot of input textfields. Each textfield has this code structure:

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'),
                ),

In the initState() function I call a method that pulls data from a Firestore collection and populates the TextEditingController associated with each textfield.

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

It is in this function that I try to get the data using a StreamBuilder. Here is the code.

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();
}

The problem I am having is when I run the code through the debugger and try to step through the code I get to the line StreamBuilder and then I am taken out of the function. None of the code inside the StreamBuilder gets executed but there is no error either.

I am thinking that I can not use a StreamBuilder outside the "build" function.

@override
  Widget build(BuildContext context) {

Is this correct or am I missing something else?

Do it like this

  late final StreamSubscription myStream;

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

Make sure to dispose the stream once done

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

Throwaway expressions

Let's suppose you have a Printer class, where you can display a message and do something whenever a message is displayed:

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

Now, let's use it:

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

If you run this code, nothing will happen because you didn't call the show method. The above is an example of what I call throwaway expression , because nothing happens besides Dart creating an object and clearing it from memory.

The below snippet will work:

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

This will output

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

The build method

Generally, when you start a Flutter app by creating a MaterialApp , Flutter looks into its home argument (which is a Widget) and calls its build method. This widget will go through all its children declared inside its build method and will call their build methods. This process repeats until there is no more children.

When a Widget's build method is called, some logic is executed. Therefore, if you place a Widget A outside the build method, A's logic will not be executed (unless you explicitely call A's build method, but for this you will need a BuildContext ) and it'll be a throwaway expression . So you're correct when you say

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

The solution

  1. Put your StreamBuilder inside your build method.

  2. Use a StreamSubscription .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM