Unverified Commit 49adef67 authored by Shi-Hao Hong's avatar Shi-Hao Hong Committed by GitHub

[State Restoration] Code sample templates, migrate existing code samples (#78757)

* Create state restoration templates, 

* Update existing state restoration samples to use the new templates

* Add to README, decided to require stateful widgets to include RestorationMixin
parent 7a88eb97
......@@ -109,6 +109,13 @@ These templates follow the same conventions as the `WidgetsApp` templates above
- [`stateless_widget_material`](stateless_widget_material.tmpl)
- [`stateful_widget_restoration_material`](stateful_widget_restoration_material.tmpl) :
Similar to the `stateful_widget_restoration` template, but for `MaterialApp`.
- [`stateless_widget_restoration_material`](stateful_widget_restoration_material.tmpl) :
Similar to the `stateless_widget` template, but the `MaterialApp` has `restorationScopeId`
defined.
- [`stateful_widget_scaffold`](stateful_widget_scaffold.tmpl) : Adds a `Scaffold` widget as the home
of the enclosing `MaterialApp` to wrap the stateful widget snippet. The `Scaffold` widget contains
an `AppBar`.
......@@ -146,3 +153,10 @@ These templates follow the same conventions as the `WidgetsApp` templates above
- [`stateless_widget_cupertinoPageScaffold`](stateless_widget_cupertino_page_scaffold.tmpl) : Similar to
`stateless_widget_cupertino`, except that it wraps the stateless widget with a
`CupertinoPageScaffold`.
- [`stateless_widget_restoration_cupertino`](stateful_widget_restoration_material.tmpl) :
Similar to the `stateless_widget` template, but the `CupertinoApp` has `restorationScopeId`
defined.
- [`stateful_widget_restoration_cupertino`](stateful_widget_restoration_material.tmpl) :
Similar to the `stateful_widget_restoration` template, but for `CupertinoApp`.
/// Flutter code sample for {{element}}
{{description}}
{{code-dartImports}}
import 'package:flutter/cupertino.dart';
{{code-imports}}
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const CupertinoApp(
restorationScopeId: 'app',
title: _title,
home: MyStatefulWidget(restorationId: 'main'),
);
}
}
{{code-preamble}}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key, this.restorationId}) : super(key: key);
final String? restorationId;
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
/// RestorationProperty objects can be used because of RestorationMixin.
class _MyStatefulWidgetState extends State<MyStatefulWidget> with RestorationMixin {
// In this example, the restoration ID for the mixin is passed in through
// the [StatefulWidget]'s constructor.
@override
String? get restorationId => widget.restorationId;
{{code}}
}
/// Flutter code sample for {{element}}
{{description}}
{{code-dartImports}}
import 'package:flutter/material.dart';
{{code-imports}}
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
restorationScopeId: 'app',
title: _title,
home: MyStatefulWidget(restorationId: 'main'),
);
}
}
{{code-preamble}}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key, this.restorationId}) : super(key: key);
final String? restorationId;
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
/// RestorationProperty objects can be used because of RestorationMixin.
class _MyStatefulWidgetState extends State<MyStatefulWidget> with RestorationMixin {
// In this example, the restoration ID for the mixin is passed in through
// the [StatefulWidget]'s constructor.
@override
String? get restorationId => widget.restorationId;
{{code}}
}
/// Flutter code sample for {{element}}
{{description}}
{{code-dartImports}}
import 'package:flutter/cupertino.dart';
{{code-imports}}
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const CupertinoApp(
restorationScopeId: 'app',
title: _title,
home: MyStatelessWidget(),
);
}
}
{{code-preamble}}
/// This is the stateless widget that the main application instantiates.
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({Key? key}) : super(key: key);
@override
{{code}}
}
/// Flutter code sample for {{element}}
{{description}}
{{code-dartImports}}
import 'package:flutter/material.dart';
{{code-imports}}
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
restorationScopeId: 'app',
title: _title,
home: MyStatelessWidget(),
);
}
}
{{code-preamble}}
/// This is the stateless widget that the main application instantiates.
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({Key? key}) : super(key: key);
@override
{{code}}
}
......@@ -1127,7 +1127,7 @@ class CupertinoModalPopupRoute<T> extends PopupRoute<T> {
///
/// For more information about state restoration, see [RestorationManager].
///
/// {@tool sample --template=freeform}
/// {@tool sample --template=stateless_widget_restoration_cupertino}
///
/// This sample demonstrates how to create a restorable Cupertino modal route.
/// This is accomplished by enabling state restoration by specifying
......@@ -1136,29 +1136,20 @@ class CupertinoModalPopupRoute<T> extends PopupRoute<T> {
///
/// {@macro flutter.widgets.RestorationManager}
///
/// ```dart imports
/// import 'package:flutter/cupertino.dart';
/// ```
///
/// ```dart
/// void main() {
/// runApp(const MyApp());
/// }
///
/// class MyApp extends StatelessWidget {
/// const MyApp({Key? key}) : super(key: key);
///
/// @override
/// Widget build(BuildContext context) {
/// return const CupertinoApp(
/// restorationScopeId: 'app',
/// home: MyHomePage(),
/// return CupertinoPageScaffold(
/// navigationBar: const CupertinoNavigationBar(
/// middle: Text('Home'),
/// ),
/// child: Center(child: CupertinoButton(
/// onPressed: () {
/// Navigator.of(context).restorablePush(_modalBuilder);
/// },
/// child: const Text('Open Modal'),
/// )),
/// );
/// }
/// }
///
/// class MyHomePage extends StatelessWidget {
/// const MyHomePage({Key? key}) : super(key: key);
///
/// static Route<void> _modalBuilder(BuildContext context, Object? arguments) {
/// return CupertinoModalPopupRoute<void>(
......@@ -1184,22 +1175,6 @@ class CupertinoModalPopupRoute<T> extends PopupRoute<T> {
/// },
/// );
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return CupertinoPageScaffold(
/// navigationBar: const CupertinoNavigationBar(
/// middle: Text('Home'),
/// ),
/// child: Center(child: CupertinoButton(
/// onPressed: () {
/// Navigator.of(context).restorablePush(_modalBuilder);
/// },
/// child: const Text('Open Modal'),
/// )),
/// );
/// }
/// }
/// ```
///
/// {@end-tool}
......@@ -1293,7 +1268,7 @@ Widget _buildCupertinoDialogTransitions(BuildContext context, Animation<double>
///
/// For more information about state restoration, see [RestorationManager].
///
/// {@tool sample --template=freeform}
/// {@tool sample --template=stateless_widget_restoration_cupertino}
///
/// This sample demonstrates how to create a restorable Cupertino dialog. This is
/// accomplished by enabling state restoration by specifying
......@@ -1302,29 +1277,20 @@ Widget _buildCupertinoDialogTransitions(BuildContext context, Animation<double>
///
/// {@macro flutter.widgets.RestorationManager}
///
/// ```dart imports
/// import 'package:flutter/cupertino.dart';
/// ```
///
/// ```dart
/// void main() {
/// runApp(const MyApp());
/// }
///
/// class MyApp extends StatelessWidget {
/// const MyApp({Key? key}) : super(key: key);
///
/// @override
/// Widget build(BuildContext context) {
/// return const CupertinoApp(
/// restorationScopeId: 'app',
/// home: MyHomePage(),
/// return CupertinoPageScaffold(
/// navigationBar: const CupertinoNavigationBar(
/// middle: Text('Home'),
/// ),
/// child: Center(child: CupertinoButton(
/// onPressed: () {
/// Navigator.of(context).restorablePush(_dialogBuilder);
/// },
/// child: const Text('Open Dialog'),
/// )),
/// );
/// }
/// }
///
/// class MyHomePage extends StatelessWidget {
/// const MyHomePage({Key? key}) : super(key: key);
///
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// return CupertinoDialogRoute<void>(
......@@ -1341,22 +1307,6 @@ Widget _buildCupertinoDialogTransitions(BuildContext context, Animation<double>
/// },
/// );
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return CupertinoPageScaffold(
/// navigationBar: const CupertinoNavigationBar(
/// middle: Text('Home'),
/// ),
/// child: Center(child: CupertinoButton(
/// onPressed: () {
/// Navigator.of(context).restorablePush(_dialogBuilder);
/// },
/// child: const Text('Open Dialog'),
/// )),
/// );
/// }
/// }
/// ```
///
/// {@end-tool}
......
......@@ -111,48 +111,16 @@ const double _inputFormLandscapeHeight = 108.0;
///
/// For more information about state restoration, see [RestorationManager].
///
/// {@tool sample --template=freeform}
/// {@macro flutter.widgets.RestorationManager}
///
/// {@tool sample --template=stateful_widget_restoration_material}
///
/// This sample demonstrates how to create a restorable Material date picker.
/// This is accomplished by enabling state restoration by specifying
/// [MaterialApp.restorationScopeId] and using [Navigator.restorablePush] to
/// push [DatePickerDialog] when the button is tapped.
///
/// {@macro flutter.widgets.RestorationManager}
///
/// ```dart imports
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart
/// void main() {
/// runApp(const MyApp());
/// }
///
/// class MyApp extends StatelessWidget {
/// const MyApp({Key? key}) : super(key: key);
///
/// @override
/// Widget build(BuildContext context) {
/// return const MaterialApp(
/// restorationScopeId: 'app',
/// title: 'Restorable Date Picker Demo',
/// home: MyHomePage(),
/// );
/// }
/// }
///
/// class MyHomePage extends StatefulWidget {
/// const MyHomePage({Key? key}) : super(key: key);
///
/// @override
/// _MyHomePageState createState() => _MyHomePageState();
/// }
///
/// class _MyHomePageState extends State<MyHomePage> with RestorationMixin {
/// @override
/// String get restorationId => 'scaffold_state';
///
/// final RestorableDateTime _selectedDate = RestorableDateTime(DateTime(2021, 7, 25));
/// late final RestorableRouteFuture<DateTime?> _restorableDatePickerRouteFuture = RestorableRouteFuture<DateTime?>(
/// onComplete: _selectDate,
......@@ -213,7 +181,6 @@ const double _inputFormLandscapeHeight = 108.0;
/// ),
/// );
/// }
/// }
/// ```
///
/// {@end-tool}
......@@ -969,43 +936,14 @@ class _DatePickerHeader extends StatelessWidget {
///
/// {@macro flutter.widgets.RestorationManager}
///
/// {@tool sample --template=freeform}
/// {@tool sample --template=stateful_widget_restoration_material}
///
/// This sample demonstrates how to create a restorable Material date range picker.
/// This is accomplished by enabling state restoration by specifying
/// [MaterialApp.restorationScopeId] and using [Navigator.restorablePush] to
/// push [DateRangePickerDialog] when the button is tapped.
///
/// ```dart imports
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart
/// void main() {
/// runApp(const MyApp());
/// }
///
/// class MyApp extends StatelessWidget {
/// const MyApp({Key? key}) : super(key: key);
///
/// @override
/// Widget build(BuildContext context) {
/// return const MaterialApp(
/// restorationScopeId: 'app',
/// title: 'Restorable Date Range Picker Demo',
/// home: MyHomePage(),
/// );
/// }
/// }
///
/// class MyHomePage extends StatefulWidget {
/// const MyHomePage({Key? key}) : super(key: key);
///
/// @override
/// _MyHomePageState createState() => _MyHomePageState();
/// }
///
/// class _MyHomePageState extends State<MyHomePage> with RestorationMixin {
/// final RestorableDateTimeN _startDate = RestorableDateTimeN(DateTime(2021, 1, 1));
/// final RestorableDateTimeN _endDate = RestorableDateTimeN(DateTime(2021, 1, 5));
/// late final RestorableRouteFuture<DateTimeRange?> _restorableDateRangePickerRouteFuture = RestorableRouteFuture<DateTimeRange?>(
......@@ -1031,9 +969,6 @@ class _DatePickerHeader extends StatelessWidget {
/// }
///
/// @override
/// String get restorationId => 'scaffold_state';
///
/// @override
/// void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
/// registerForRestoration(_startDate, 'start_date');
/// registerForRestoration(_endDate, 'end_date');
......@@ -1080,7 +1015,6 @@ class _DatePickerHeader extends StatelessWidget {
/// ),
/// );
/// }
/// }
/// ```
///
/// {@end-tool}
......
......@@ -994,7 +994,7 @@ Widget _buildMaterialDialogTransitions(BuildContext context, Animation<double> a
///
/// For more information about state restoration, see [RestorationManager].
///
/// {@tool sample --template=freeform}
/// {@tool sample --template=stateless_widget_restoration_material}
///
/// This sample demonstrates how to create a restorable Material dialog. This is
/// accomplished by enabling state restoration by specifying
......@@ -1003,39 +1003,7 @@ Widget _buildMaterialDialogTransitions(BuildContext context, Animation<double> a
///
/// {@macro flutter.widgets.RestorationManager}
///
/// ```dart imports
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart
/// void main() {
/// runApp(const MyApp());
/// }
///
/// class MyApp extends StatelessWidget {
/// const MyApp({Key? key}) : super(key: key);
///
/// @override
/// Widget build(BuildContext context) {
/// return const MaterialApp(
/// restorationScopeId: 'app',
/// title: 'Restorable Routes Demo',
/// home: MyHomePage(),
/// );
/// }
/// }
///
/// class MyHomePage extends StatelessWidget {
/// const MyHomePage({Key? key}) : super(key: key);
///
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// return DialogRoute<void>(
/// context: context,
/// builder: (BuildContext context) => const AlertDialog(title: Text('Material Alert!')),
/// );
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return Scaffold(
/// body: Center(
......@@ -1048,6 +1016,12 @@ Widget _buildMaterialDialogTransitions(BuildContext context, Animation<double> a
/// ),
/// );
/// }
///
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// return DialogRoute<void>(
/// context: context,
/// builder: (BuildContext context) => const AlertDialog(title: Text('Material Alert!')),
/// );
/// }
/// ```
///
......
......@@ -1901,7 +1901,7 @@ class RawDialogRoute<T> extends PopupRoute<T> {
///
/// For more information about state restoration, see [RestorationManager].
///
/// {@tool sample --template=freeform}
/// {@tool sample --template=stateless_widget_restoration_material}
///
/// This sample demonstrates how to create a restorable dialog. This is
/// accomplished by enabling state restoration by specifying
......@@ -1910,29 +1910,19 @@ class RawDialogRoute<T> extends PopupRoute<T> {
///
/// {@macro flutter.widgets.RestorationManager}
///
/// ```dart imports
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart
/// void main() {
/// runApp(const MyApp());
/// }
///
/// class MyApp extends StatelessWidget {
/// const MyApp({Key? key}) : super(key: key);
///
/// @override
/// Widget build(BuildContext context) {
/// return const MaterialApp(
/// restorationScopeId: 'app',
/// home: MyHomePage(),
/// return Scaffold(
/// body: Center(
/// child: OutlinedButton(
/// onPressed: () {
/// Navigator.of(context).restorablePush(_dialogBuilder);
/// },
/// child: const Text('Open Dialog'),
/// ),
/// ),
/// );
/// }
/// }
///
/// class MyHomePage extends StatelessWidget {
/// const MyHomePage({Key? key}) : super(key: key);
///
/// static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
/// return RawDialogRoute<void>(
......@@ -1945,21 +1935,6 @@ class RawDialogRoute<T> extends PopupRoute<T> {
/// },
/// );
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return Scaffold(
/// body: Center(
/// child: OutlinedButton(
/// onPressed: () {
/// Navigator.of(context).restorablePush(_dialogBuilder);
/// },
/// child: const Text('Open Dialog'),
/// ),
/// ),
/// );
/// }
/// }
/// ```
///
/// {@end-tool}
......
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