Search code examples
flutterdartflutter-futurebuilderstream-builder

How can i make future function to wait for a stream to complete?


Future notifyRead(Guid characteristic, BuildContext context) async {
    try {
      if (await FlutterBlue.instance.isOn) {
        BluetoothCharacteristic charToTarget = _characteristics
            .firstWhere((element) => element.uuid == characteristic);
        await charToTarget.setNotifyValue(true);
        clearInfo();
        var stream = charToTarget.value.listen(
          (value) {
            var temp = String.fromCharCodes(value);
            _info.add(temp);
            print(temp);
            notifyListeners();
            if (temp.startsWith("batt")) {
              updateBattValues(temp);
            }
            updateWifiVerificationStatus();

            if (_info.length == 17) {
              log("Finished Sending Data ");
              _notifyFinished = true;
              notifyListeners();
              return;
            }
          },
        );
        await charToTarget.write(INFO.codeUnits);
      } else {
        Fluttertoast.showToast(msg: "Seems like your Bluetooth is turned off");
      }
    } catch (e) {
      log("Some error occurred in retrieving info ${e.toString()}");
      Fluttertoast.showToast(
          msg: "Some error occurred in retrieving info ${e.toString()}");
    }
  }

I want this notifyRead method to wait for the stream inside to complete.But I am not able to achieve the same.The stream does not have an end associated with it , all I know is the stream outputs 17 values(that I save in _info array ) , so the check the length of the data and mark the end. This notifyRead method is called by a button's onTap.I want to show a till the stream finishes.


Solution

  • This is very straightforward when using await for:

    void main() async {
      print('before');
      await asyncFunction();
      print('after');
    }
    
    Future<void> asyncFunction() async {
      int count = 0;
      await for (var _ in streamFunction()) {
        count++;
        print('count = $count');
        if (count == 17) {
          break;
        }
      }
    }
    
    Stream<int> streamFunction() async* {
      for (var i = 0; ; i++) {
        yield i;
      }
    }
    

    Output:

    before
    count = 1
    count = 2
    count = 3
    count = 4
    count = 5
    count = 6
    count = 7
    count = 8
    count = 9
    count = 10
    count = 11
    count = 12
    count = 13
    count = 14
    count = 15
    count = 16
    count = 17
    after