From 56800d8fa1403110ce6f4d7faa0c0acdc9440c81 Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Mon, 23 Jul 2018 22:56:03 -0700 Subject: [PATCH] Improve docs for FutureBuilder (#19687) --- packages/flutter/lib/src/widgets/async.dart | 33 +++++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/flutter/lib/src/widgets/async.dart b/packages/flutter/lib/src/widgets/async.dart index 418aa873cf..3553bc29af 100644 --- a/packages/flutter/lib/src/widgets/async.dart +++ b/packages/flutter/lib/src/widgets/async.dart @@ -411,12 +411,31 @@ class StreamBuilder extends StreamBuilderBase> { /// Widget that builds itself based on the latest snapshot of interaction with /// a [Future]. /// +/// The [future] must have been obtained earlier, e.g. during [State.initState], +/// [State.didUpdateConfig], or [State.didChangeDependencies]. It must not be +/// created during the [State.build] or [StatelessWidget.build] method call when +/// constructing the [FutureBuilder]. If the [future] is created at the same +/// time as the [FutureBuilder], then every time the [FutureBuilder]'s parent is +/// rebuilt, the asynchronous task will be restarted. +/// +/// A general guideline is to assume that every `build` method could get called +/// every frame, and to treat omitted calls as an optimization. +/// +/// ## Timing +/// /// Widget rebuilding is scheduled by the completion of the future, using /// [State.setState], but is otherwise decoupled from the timing of the future. /// The [builder] callback is called at the discretion of the Flutter pipeline, and /// will thus receive a timing-dependent sub-sequence of the snapshots that /// represent the interaction with the future. /// +/// A side-effect of this is that providing a new but already-completed future +/// to a [FutureBuilder] will result in a single frame in the +/// [ConnectionState.waiting] state. This is because there is no way to +/// synchronously determine that a [Future] has already completed. +/// +/// ## Builder contract +/// /// For a future that completes successfully with data, assuming [initialData] /// is null, the [builder] will be called with either both or only the latter of /// the following snapshots: @@ -459,16 +478,18 @@ class StreamBuilder extends StreamBuilderBase> { /// /// ```dart /// new FutureBuilder( -/// future: _calculation, // a Future or null +/// future: _calculation, // a previously-obtained Future or null /// builder: (BuildContext context, AsyncSnapshot snapshot) { /// switch (snapshot.connectionState) { -/// case ConnectionState.none: return new Text('Press button to start'); -/// case ConnectionState.waiting: return new Text('Awaiting result...'); -/// default: +/// case ConnectionState.none: +/// return new Text('Press button to start.'); +/// case ConnectionState.active: +/// case ConnectionState.waiting: +/// return new Text('Awaiting result...'); +/// case ConnectionState.done: /// if (snapshot.hasError) /// return new Text('Error: ${snapshot.error}'); -/// else -/// return new Text('Result: ${snapshot.data}'); +/// return new Text('Result: ${snapshot.data}'); /// } /// }, /// )