Skip to content

Commit

Permalink
Add InheritedWidget demo
Browse files Browse the repository at this point in the history
for issue X-Wei#8
  • Loading branch information
X-Wei committed Feb 15, 2019
1 parent dff5e40 commit d373ce5
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 1 deletion.
15 changes: 14 additions & 1 deletion lib/my_app_meta.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import './routes/plugins_image_picker_ex.dart';
import './routes/plugins_local_auth_ex.dart';
import './routes/plugins_markdown_ex.dart';
import './routes/plugins_webview_ex.dart';
import './routes/state_inherited_widget_ex.dart';
import './routes/widgets_buttons_ex.dart';
import './routes/widgets_card_ex.dart';
import './routes/widgets_dropdown_button_ex.dart';
Expand Down Expand Up @@ -132,7 +133,7 @@ class MyRouteGroup {
const kMyAppRoutesStructure = <MyRouteGroup>[
MyRouteGroup(
groupName: 'Widgets',
icon: Icon(Icons.widgets),
icon: Icon(Icons.extension),
routes: <MyRoute>[
IconExample(),
TextExample(),
Expand Down Expand Up @@ -213,6 +214,18 @@ const kMyAppRoutesStructure = <MyRouteGroup>[
FileReadWriteExample(),
],
),
MyRouteGroup(
groupName: 'State Management',
icon: Icon(Icons.developer_mode),
routes: <MyRoute>[
InheritedWidgetExample(),
// TODO ScopedModelExample(),
// TODO StreamBuilderExample(),
// TODO StreamControllerExample(),
// TODO BlocExample(),
// TODO ReduxExample(),
],
),
MyRouteGroup(
groupName: 'Plugins',
icon: Icon(Icons.power),
Expand Down
151 changes: 151 additions & 0 deletions lib/routes/state_inherited_widget_ex.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import 'package:flutter/material.dart';
import '../my_route.dart';

class InheritedWidgetExample extends MyRoute {
const InheritedWidgetExample(
[String sourceFile = 'lib/routes/state_inherited_widget_ex.dart'])
: super(sourceFile);

@override
get title => 'InheritedWidget';

@override
get description => 'Access state of widgets up the tree.';

@override
get links => {
'Doc':
'https://docs.flutter.io/flutter/widgets/InheritedWidget-class.html',
'Youtube': 'https://www.youtube.com/watch?v=4I68ilX0Y24',
};

@override
Widget buildMyRouteContent(BuildContext context) {
return InheritedWidgetDemo();
}
}

class InheritedWidgetDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: MyDemo(),
);
}
}

// ###1. Define an InheritedWidget that stores `MyDemoState` (c.f. the
// 'MyDemo' StatefulWidget that we defined below).
// All descendants of this widget can access `myState` by:
// final stateOfParent = MyInheritedWidget.of(context).myState;
// NOTE: InheritedWidget are *stateless*.
class MyInheritedWidget extends InheritedWidget {
final MyDemoState myState;

MyInheritedWidget({Key key, Widget child, @required this.myState})
: super(key: key, child: child);

@override
// Returns when it's children widget should be notified for rebuild.
bool updateShouldNotify(MyInheritedWidget oldWidget) {
return this.myState.counterValue != oldWidget.myState.counterValue;
}

static MyInheritedWidget of(BuildContext context) {
return context.inheritFromWidgetOfExactType(MyInheritedWidget);
}
}

// ###2. Define a stateFUL widget where the corresponding State<MyDemo> is to be
// fetched by children widgets.
class MyDemo extends StatefulWidget {
@override
MyDemoState createState() => MyDemoState();
}

class MyDemoState extends State<MyDemo> {
// In this demo the state is just _counter.
int _counter = 0;

int get counterValue => _counter;

// Note: these state-mutating functions must be wrapped by setState.
void incrementCounter() => setState(() => _counter++);
void decrementCounter() => setState(() => _counter--);

@override
Widget build(BuildContext context) {
// ###3. Put the inherited widget at the root of the widget tree, so that
// all children widgets can access the state.
return MyInheritedWidget(
myState: this,
child: ListView(
children: <Widget>[
Text("InheritedWidget allows efficient sharing of app's state down "
"the widgets tree.\n\n"
"In this example, the app's root widget is an InheritedWidget, "
"so it's state is shared to the two `CounterAndButtons` widgets "
"below. \n\n"
"Clicking on child widget's button would update the root "
"widget's counter.\n\n"
"Note: Recommend using ScopedModel for CHANGING parent's state "
"from child widget*.\n"),
_buildRootWidget(),
],
),
);
}

Widget _buildRootWidget() {
return Card(
elevation: 4.0,
child: Column(
children: <Widget>[
Text('(root widget)'),
Text(
'${this.counterValue}',
style: Theme.of(context).textTheme.display1,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[CounterAndButton(), CounterAndButton()],
),
],
),
);
}
}

class CounterAndButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 3. Retrieve parent widget's state.
final rootWidgetsState = MyInheritedWidget.of(context).myState;
return Card(
margin: EdgeInsets.all(4.0).copyWith(bottom: 32.0),
color: Colors.white70,
child: Column(
children: <Widget>[
Text('(child widget)'),
Text(
'${rootWidgetsState.counterValue}',
style: Theme.of(context).textTheme.display1,
),
ButtonBar(
children: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: () => rootWidgetsState.incrementCounter(),
),
IconButton(
icon: Icon(Icons.remove),
onPressed: () => rootWidgetsState.decrementCounter(),
),
],
)
],
),
);
}
}

0 comments on commit d373ce5

Please sign in to comment.