setState documentation (#132090)
Fixes https://github.com/flutter/flutter/issues/12296
This commit is contained in:
parent
eb126ccfc7
commit
1e35d3a6b7
@ -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(() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user