feat: Added docstring examples to AnimatedBuilder and ChangeNotifier (#98628)

This commit is contained in:
Alberto 2022-02-28 21:41:20 +01:00 committed by GitHub
parent 7b6040ce27
commit b44cbe1dd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 121 additions and 2 deletions

View File

@ -6,7 +6,7 @@ documentation in the framework.
The examples can be run individually by just specifying the path to the example
on the command line (or in the run configuration of an IDE).
For example (no pun intended!), to run, the first example from the `Curve2D`
For example (no pun intended!), to run the first example from the `Curve2D`
class in Chrome, you would run it like so from the [api](.) directory:
```

View File

@ -0,0 +1,65 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flutter code sample for ChangeNotifier with an AnimatedBuilder
import 'package:flutter/material.dart';
class CounterBody extends StatelessWidget {
const CounterBody({Key? key, required this.counterValueNotifier}) : super(key: key);
final ValueNotifier<int> counterValueNotifier;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Current counter value:'),
// Thanks to the [AnimatedBuilder], only the widget displaying the
// current count is rebuilt when `counterValueNotifier` notifies its
// listeners. The [Text] widget above and [CounterBody] itself aren't
// rebuilt.
AnimatedBuilder(
// [AnimatedBuilder] accepts any [Listenable] subtype.
animation: counterValueNotifier,
builder: (BuildContext context, Widget? child) {
return Text('${counterValueNotifier.value}');
},
),
],
),
);
}
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('AnimatedBuilder example')),
body: CounterBody(counterValueNotifier: _counter),
floatingActionButton: FloatingActionButton(
onPressed: () => _counter.value++,
child: const Icon(Icons.add),
),
),
);
}
}
void main() {
runApp(const MyApp());
}

View File

@ -0,0 +1,33 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/foundation/change_notifier/change_notifier.0.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Smoke test for MyApp', (WidgetTester tester) async {
await tester.pumpWidget(const MyApp());
expect(find.byType(Scaffold), findsOneWidget);
expect(find.byType(CounterBody), findsOneWidget);
expect(find.byType(FloatingActionButton), findsOneWidget);
expect(find.text('Current counter value:'), findsOneWidget);
});
testWidgets('Counter update', (WidgetTester tester) async {
await tester.pumpWidget(const MyApp());
// Initial state of the counter
expect(find.text('0'), findsOneWidget);
// Tapping the increase button
await tester.tap(find.byType(FloatingActionButton));
await tester.pumpAndSettle();
// Counter should be at 1
expect(find.text('1'), findsOneWidget);
expect(find.text('0'), findsNothing);
});
}

View File

@ -98,6 +98,8 @@ abstract class ValueListenable<T> extends Listenable {
/// It is O(1) for adding listeners and O(N) for removing listeners and dispatching
/// notifications (where N is the number of listeners).
///
/// {@macro flutter.flutter.animatedbuilder_changenotifier.rebuild}
///
/// See also:
///
/// * [ValueNotifier], which is a [ChangeNotifier] that wraps a single value.

View File

@ -979,7 +979,7 @@ class DefaultTextStyleTransition extends AnimatedWidget {
/// rebuilding it on every animation tick.
///
/// If you pass the pre-built subtree as the [child] parameter, the
/// AnimatedBuilder will pass it back to your builder function so that you
/// [AnimatedBuilder] will pass it back to your builder function so that you
/// can incorporate it into your build.
///
/// Using this pre-built child is entirely optional, but can improve
@ -993,6 +993,25 @@ class DefaultTextStyleTransition extends AnimatedWidget {
/// ** See code in examples/api/lib/widgets/transitions/animated_builder.0.dart **
/// {@end-tool}
///
/// {@template flutter.flutter.animatedbuilder_changenotifier.rebuild}
/// ## Improve rebuilds performance using AnimatedBuilder
///
/// Despite the name, [AnimatedBuilder] is not limited to [Animation]s. Any subtype
/// of [Listenable] (such as [ChangeNotifier] and [ValueNotifier]) can be used with
/// an [AnimatedBuilder] to rebuild only certain parts of a widget when the
/// [Listenable] notifies its listeners. This technique is a performance improvement
/// that allows rebuilding only specific widgets leaving others untouched.
///
/// {@tool dartpad}
/// The following example implements a simple counter that utilizes an
/// [AnimatedBuilder] to limit rebuilds to only the [Text] widget. The current count
/// is stored in a [ValueNotifier], which rebuilds the [AnimatedBuilder]'s contents
/// when its value is changed.
///
/// ** See code in examples/api/lib/foundation/change_notifier/change_notifier.0.dart **
/// {@end-tool}
/// {@endtemplate}
///
/// See also:
///
/// * [TweenAnimationBuilder], which animates a property to a target value