Search code examples
flutterlicensingflutter-dependencies

Why does the LicenseRegistry in flutter return a Stream<LicenseEntry> and not a List<LicenseEntry>?


I would like to unterstand why LicenseRegistry.licenses returns Stream<LicenseEntry> and not List<LicenseEntry>? Wouldn't a simple list make more sense here instead of a Stream?

The dart documentation states a Stream as the following:

A Stream provides a way to receive a sequence of events. Each event is either a data event, also called an element of the stream, or an error event, which is a notification that something has failed. When a stream has emitted all its event, a single "done" event will notify the listener that the end has been reached.

Can maybe anyone explain the relationship between a List of licenses and the description of a Stream?

The flutter documentation states that LicenseRegistry.licenses is an expensive operation. Is the fact that it returns a Stream correlated to that?

Sources:

https://api.dart.dev/stable/2.8.2/dart-async/Stream-class.html https://api.flutter.dev/flutter/foundation/LicenseRegistry/licenses.html


Solution

  • A stream is useful (as here) when partial results are useful to the consumer. In this case the normal consumer is the LicensePage widget. It listens to the stream using await for and as it gets each package's licenses it adds them to the page with a setState. In this way it can begin to render the final page as work continues to deliver more licenses. (The await for loop terminates if the widget is unmounted while it is still in progress, so that the rest of the page isn't formatted and rendered if the license page is closed.)

    If, instead, the return value were a list, that list would have to be built before the first license could be rendered.

    In an interesting twist, the LicensePage widget has to extract the paragraphs from each LicenseEntry which are delivered by an iterable. It converts them to a list in a background task! So, it processes each set of paragraphs from a particular entry in a group.

      final List<LicenseParagraph> paragraphs =
        await SchedulerBinding.instance.scheduleTask<List<LicenseParagraph>>(
          license.paragraphs.toList,
          Priority.animation,
          debugLabel: 'License',
        );