Use callbacks for sending messages up the app

Using .of() to call mutating setters is not great practice since it ties

parts of the app together in ways that prevent reuse and composition.



Since people are now using the gallery app to copy from, let's use the

better practice of using callbacks.
This commit is contained in:
Ian Hickson 2016-04-04 15:25:06 -07:00
parent 08bb332cbb
commit d748186c51
3 changed files with 55 additions and 36 deletions

View File

@ -3,34 +3,32 @@
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart' show timeDilation;
import 'home.dart';
class GalleryApp extends StatefulWidget {
GalleryApp({ Key key }) : super(key: key);
static GalleryAppState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher<GalleryAppState>());
@override
GalleryAppState createState() => new GalleryAppState();
}
class GalleryAppState extends State<GalleryApp> {
bool _lightTheme = true;
bool get lightTheme => _lightTheme;
void set lightTheme(bool value) {
setState(() {
_lightTheme = value;
});
}
bool _useLightTheme = true;
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Material Gallery',
theme: lightTheme ? _kGalleryLightTheme : _kGalleryDarkTheme,
theme: _useLightTheme ? _kGalleryLightTheme : _kGalleryDarkTheme,
routes: {
'/': (BuildContext context) => new GalleryHome()
'/': (BuildContext context) => new GalleryHome(
theme: _useLightTheme,
onThemeChanged: (bool value) { setState(() { _useLightTheme = value; }); },
timeDilation: timeDilation,
onTimeDilationChanged: (double value) { setState(() { timeDilation = value; }); }
)
}
);
}

View File

@ -3,23 +3,24 @@
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart' show timeDilation;
import 'package:flutter/widgets.dart';
import 'app.dart';
class GalleryDrawer extends StatelessWidget {
GalleryDrawer({ Key key }) : super(key: key);
void _changeTheme(BuildContext context, bool value) {
GalleryApp.of(context).lightTheme = value;
GalleryDrawer({
Key key,
this.theme,
this.onThemeChanged,
this.timeDilation,
this.onTimeDilationChanged
}) : super(key: key) {
assert(onThemeChanged != null);
assert(onTimeDilationChanged != null);
}
void _toggleAnimationSpeed(BuildContext context) {
GalleryApp.of(context).setState(() {
timeDilation = (timeDilation != 1.0) ? 1.0 : 5.0;
});
}
final bool theme;
final ValueChanged<bool> onThemeChanged;
final double timeDilation;
final ValueChanged<double> onTimeDilationChanged;
@override
Widget build(BuildContext context) {
@ -29,30 +30,30 @@ class GalleryDrawer extends StatelessWidget {
new DrawerHeader(child: new Text('Flutter Gallery')),
new DrawerItem(
icon: Icons.brightness_5,
onPressed: () { _changeTheme(context, true); },
selected: GalleryApp.of(context).lightTheme,
onPressed: () { onThemeChanged(true); },
selected: theme,
child: new Row(
children: <Widget>[
new Flexible(child: new Text('Light')),
new Radio<bool>(
value: true,
groupValue: GalleryApp.of(context).lightTheme,
onChanged: (bool value) { _changeTheme(context, value); }
groupValue: theme,
onChanged: onThemeChanged
)
]
)
),
new DrawerItem(
icon: Icons.brightness_7,
onPressed: () { _changeTheme(context, false); },
selected: !GalleryApp.of(context).lightTheme,
onPressed: () { onThemeChanged(false); },
selected: theme,
child: new Row(
children: <Widget>[
new Flexible(child: new Text('Dark')),
new Radio<bool>(
value: false,
groupValue: GalleryApp.of(context).lightTheme,
onChanged: (bool value) { _changeTheme(context, value); }
groupValue: theme,
onChanged: onThemeChanged
)
]
)
@ -61,13 +62,13 @@ class GalleryDrawer extends StatelessWidget {
new DrawerItem(
icon: Icons.hourglass_empty,
selected: timeDilation != 1.0,
onPressed: () { _toggleAnimationSpeed(context); },
onPressed: () { onTimeDilationChanged(timeDilation != 1.0 ? 1.0 : 20.0); },
child: new Row(
children: <Widget>[
new Flexible(child: new Text('Animate Slowly')),
new Checkbox(
value: timeDilation != 1.0,
onChanged: (bool value) { _toggleAnimationSpeed(context); }
onChanged: (bool value) { onTimeDilationChanged(value ? 20.0 : 1.0); }
)
]
)

View File

@ -44,7 +44,22 @@ import '../demo/weather_demo.dart';
const double _kFlexibleSpaceMaxHeight = 256.0;
class GalleryHome extends StatefulWidget {
GalleryHome({ Key key }) : super(key: key);
GalleryHome({
Key key,
this.theme,
this.onThemeChanged,
this.timeDilation,
this.onTimeDilationChanged
}) : super(key: key) {
assert(onThemeChanged != null);
assert(onTimeDilationChanged != null);
}
final bool theme;
final ValueChanged<bool> onThemeChanged;
final double timeDilation;
final ValueChanged<double> onTimeDilationChanged;
@override
GalleryHomeState createState() => new GalleryHomeState();
@ -60,7 +75,12 @@ class GalleryHomeState extends State<GalleryHome> {
return new Scaffold(
key: _homeKey,
drawer: new GalleryDrawer(),
drawer: new GalleryDrawer(
theme: config.theme,
onThemeChanged: config.onThemeChanged,
timeDilation: config.timeDilation,
onTimeDilationChanged: config.onTimeDilationChanged
),
appBar: new AppBar(
expandedHeight: _kFlexibleSpaceMaxHeight,
flexibleSpace: (BuildContext context) => new FlexibleSpaceBar(