Unverified Commit 1e35d3a6 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

setState documentation (#132090)

Fixes https://github.com/flutter/flutter/issues/12296
parent eb126ccf
......@@ -458,8 +458,9 @@ class _SnippetChecker {
}
static const List<String> ignoresDirectives = <String>[
'// ignore_for_file: duplicate_ignore',
'// ignore_for_file: directives_ordering',
'// ignore_for_file: duplicate_ignore',
'// ignore_for_file: no_leading_underscores_for_local_identifiers',
'// ignore_for_file: prefer_final_locals',
'// ignore_for_file: unnecessary_import',
'// ignore_for_file: unreachable_from_main',
......
......@@ -45,6 +45,7 @@ export 'package:flutter/rendering.dart' show RenderBox, RenderObject, debugDumpL
// late Object? _myState, newValue;
// int _counter = 0;
// Future<Directory> getApplicationDocumentsDirectory() async => Directory('');
// late AnimationController animation;
// An annotation used by test_analysis package to verify patterns are followed
// that allow for tree-shaking of both fields and their initializers. This
......@@ -1092,9 +1093,73 @@ abstract class State<T extends StatefulWidget> with Diagnosticable {
/// }
/// ```
///
/// Sometimes, the changed state is in some other object not owned by the
/// widget [State], but the widget nonetheless needs to be updated to react to
/// the new state. This is especially common with [Listenable]s, such as
/// [AnimationController]s.
///
/// In such cases, it is good practice to leave a comment in the callback
/// passed to [setState] that explains what state changed:
///
/// ```dart
/// void _update() {
/// setState(() { /* The animation changed. */ });
/// }
/// //...
/// animation.addListener(_update);
/// ```
///
/// It is an error to call this method after the framework calls [dispose].
/// You can determine whether it is legal to call this method by checking
/// whether the [mounted] property is true.
/// whether the [mounted] property is true. That said, it is better practice
/// to cancel whatever work might trigger the [setState] rather than merely
/// checking for [mounted] before calling [setState], as otherwise CPU cycles
/// will be wasted.
///
/// ## Design discussion
///
/// The original version of this API was a method called `markNeedsBuild`, for
/// consistency with [RenderObject.markNeedsLayout],
/// [RenderObject.markNeedsPaint], _et al_.
///
/// However, early user testing of the Flutter framework revealed that people
/// would call `markNeedsBuild()` much more often than necessary. Essentially,
/// people used it like a good luck charm, any time they weren't sure if they
/// needed to call it, they would call it, just in case.
///
/// Naturally, this led to performance issues in applications.
///
/// When the API was changed to take a callback instead, this practice was
/// greatly reduced. One hypothesis is that prompting developers to actually
/// update their state in a callback caused developers to think more carefully
/// about what exactly was being updated, and thus improved their understanding
/// of the appropriate times to call the method.
///
/// In practice, the [setState] method's implementation is trivial: it calls
/// the provided callback synchronously, then calls [Element.markNeedsBuild].
///
/// ## Performance considerations
///
/// There is minimal _direct_ overhead to calling this function, and as it is
/// expected to be called at most once per frame, the overhead is irrelevant
/// anyway. Nonetheless, it is best to avoid calling this function redundantly
/// (e.g. in a tight loop), as it does involve creating a closure and calling
/// it. The method is idempotent, there is no benefit to calling it more than
/// once per [State] per frame.
///
/// The _indirect_ cost of causing this function, however, is high: it causes
/// the widget to rebuild, possibly triggering rebuilds for the entire subtree
/// rooted at this widget, and further triggering a relayout and repaint of
/// the entire corresponding [RenderObject] subtree.
///
/// For this reason, this method should only be called when the [build] method
/// will, as a result of whatever state change was detected, change its result
/// meaningfully.
///
/// See also:
///
/// * [StatefulWidget], the API documentation for which has a section on
/// performance considerations that are relevant here.
@protected
void setState(VoidCallback fn) {
assert(() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment