简体   繁体   中英

How to invoke streams from within a stream in Dart

I want to output progress messages, while I download files and populate my database in my flutter app.

For this, I am using a StreamBuilder and a Stream that yields status message updates while performing work.

So far so good, but now I would like to show some details about the download progress in addition to my status messages. As far as I understand, I can wrap the download progress in another stream, but now I am a little stuck as to how I would invoke that stream from within my status updating stream.

The code looks like this right now:

  Stream<String> _upsertResult(context) async* {
    yield "Downloading Identifiers... (1/6)";
    await IdentifierService.downloadIdentifiers();
    yield "Upserting Identifiers... (2/6)";
    await IdentifierService.upsertIdentifiers();
    yield "Downloading Locations... (3/6)";
    await LocationService.downloadLocations();
    yield "Upserting Locations... (4/6)";
    await LocationService.upsertLocations();
    yield "Downloading Identifiables... (5/6)";
    await IdentifiableService.downloadIdentifiables();
    yield "Upserting Identifiables... (6/6)";
    await IdentifiableService.upsertIdentifiables();
    SchedulerBinding.instance.addPostFrameCallback((_) {
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(builder: (context) => CurtainInformationScreen()),
      );
    });
  }

Right now downloadIdentifiers() is implemented as a Future, but I could rewrite it as a Stream, in order to be able to yield download progress status updates.

I think I can listen to a new Stream I create and re-yield it in my _upsertResult Stream, but I am wondering if there is a more elegant solution to my problem here, like waiting for the Stream to end, but re-yielding all results from the Stream as it runs.

I followed pskink 's advice and did it like this:

yield "Downloading Identifiers... (1/6)";
yield* IdentifierService.downloadIdentifiers();

as according to http://dart.goodev.org/articles/language/beyond-async#yield

The yield* (pronounced yield-each) statement is designed to get around this problem. The expression following yield* must denote another (sub)sequence. What yield* does is to insert all the elements of the subsequence into the sequence currently being constructed, as if we had an individual yield for each element. We can rewrite our code using yield-each as follows:

Then I can just yield inside downloadIdentifiers and the value will be handed through.

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