Skip to content

#121962 - Add ListenableFutureBuilder - #121963

Closed
MelbourneDeveloper wants to merge 14 commits into
flutter:masterfrom
MelbourneDeveloper:#121962-ListenableFutureBuilder
Closed

MelbourneDeveloper wants to merge 14 commits into
flutter:masterfrom
MelbourneDeveloper:#121962-ListenableFutureBuilder

Conversation

@MelbourneDeveloper

@MelbourneDeveloper MelbourneDeveloper commented Mar 5, 2023 •

Copy link
Copy Markdown

This PR adds the ListenableFutureBuilder widget and tests. Briefly: this widget allows you to compose StatelessWidgets with async work, and without the need to extend StatefulWidget, or use external dependency managers. For a full description of the issue and solution see #121962

This PR fixes #121962

See a live sample here

This is a draft PR and I will revisit this, and address issues as they come up. I will go over the criteria here again before full submission

Pre-launch Checklist

  • [✅] I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • [✅ ] I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • [✅ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • [✅ ] I signed the [CLA].
  • [✅ ] I listed at least one issue that this PR fixes in the description above.
  • [✅] I updated/added relevant documentation (doc comments with ///).
  • [✅ ] I added new tests to check the change I am making, or this PR is [test-exempt].
  • [✅ ] All existing and new tests are passing.

@goderbauer
goderbauer self-requested a review March 7, 2023 23:13
///
/// If your [builder] function contains a subtree that does not depend on the
/// value of the [Listenable], it's more efficient to build that subtree
/// once instead of rebuilding it on every animation tick.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: "animation tick"? AFAICT, this may not be driven by an animation?

/// value of the [Listenable], it's more efficient to build that subtree
/// once instead of rebuilding it on every animation tick.
///
/// If you pass the pre-built subtree as the [child] parameter, the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/// Using this pre-built child is entirely optional, but can improve
/// performance significantly in some cases and is therefore a good practice.
///
/// {@tool snippet}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should likely use {@tool dartpad} and include a tested code sample (see other occurrences of this in the code base).

/// waiting, and trigger rebuild on state changes without the need for setState
///
/// ```dart
// import 'package:flutter/material.dart';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't switch from /// to // here


// @override
// Widget build(BuildContext context) => MaterialApp(
// theme: ThemeData(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentation is off

if (_activeCallbackIdentity == callbackIdentity) {
setState(() {
_snapshot = AsyncSnapshot<T>.withData(ConnectionState.done, data);
_snapshot.data!.addListener(_handleChange);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line should probably be outside of the setState since it is not setting state.


void _subscribe() {
final Object callbackIdentity = Object();
_activeCallbackIdentity = callbackIdentity;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What scenario is this guarding against?

Comment on lines +15 to +22
builder: (BuildContext context, Widget? child,
AsyncSnapshot<ValueNotifier<int>> snapshot) =>
snapshot.connectionState == ConnectionState.done
? Text('${snapshot.data!.value}')
: const CircularProgressIndicator(),
),
),
);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: formatting

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(here and elsewhere in this file)

if (snapshot.connectionState == ConnectionState.done &&
snapshot.error != null) {
final dynamic error = snapshot.error as dynamic;
// ignore: avoid_dynamic_calls

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't ignore these and instead handle the value properly.

expect(find.text('1'), findsOneWidget);
});

///Notes: we need to confirm that the builder drops its reference to the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and elsewhere: add space after /// and //

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, these should just be //, not ///

@goderbauer

Copy link
Copy Markdown
Member

Looks like the analyzer is also unhappy with this change. Could you take a look?

@MelbourneDeveloper

Copy link
Copy Markdown
Author

Hi @goderbauer

I noticed that there were some issues there but was waiting for other feedback before I investigate. Is there any other feedback before I try to figure out what's going wrong here?

There is a lot of detail on the issue itself.

Thanks

@goderbauer

Copy link
Copy Markdown
Member

I left a comment on the issue as well about my high-level concerns with this setup: #121962 (comment)

@MelbourneDeveloper

Copy link
Copy Markdown
Author

Hi @goderbauer. Thanks for the detailed responses here. Sorry, I missed the activity here. I didn't realize you had already reviewed this in detail. I'm closing this draft PR because this was more of a demonstration of how the issue could be solved rather than a finished PR.

Regarding the issue itself, it doesn't appear that my suggestion is clear. I would hope to leave that open and allow for further discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introduce ListenableFutureBuilder to Simplify Using Controllers in the Composition of a StatelessWidget

2 participants