Created
October 19, 2021 19:18
-
-
Save HansMuller/58ff48447f162e8948b3f805675ca6ab to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'package:flutter/foundation.dart'; | |
| import 'package:flutter/material.dart'; | |
| // Enables sharing keyword value data with an entire app. | |
| // | |
| // AppModel.set(context, keyword, value) adds an entry to the shared data table. | |
| // | |
| // AppModel.get(context, keyword) returns the value for keyword or null. | |
| // | |
| // A widget whose build method uses AppModel.get(context, keyword) | |
| // creates a dependency on the AppModel: when the value of keyword | |
| // changes with AppModel.set(), the widget will be rebuilt. | |
| // | |
| // This Widget would be created above the WidgetApp, so that it's always available. | |
| class AppModel extends StatefulWidget { | |
| AppModel({ Key? key, required this.child }) : super(key: key); | |
| final Widget child; | |
| @override | |
| _AppModelState createState() => _AppModelState(); | |
| static Object? get(BuildContext context, Object key) { | |
| final _AppModelData model = InheritedModel.inheritFrom<_AppModelData>(context, aspect: key)!; | |
| return model.appModelState.get(key); | |
| } | |
| static void set(BuildContext context, Object key, Object value) { | |
| final _AppModelData model = context.findAncestorWidgetOfExactType<_AppModelData>()!; | |
| model.appModelState.set(key, value); | |
| } | |
| } | |
| class _AppModelState extends State<AppModel> { | |
| late Map<Object, Object> data; | |
| @override | |
| void initState() { | |
| super.initState(); | |
| data = Map<Object, Object>(); | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| return _AppModelData(appModelState: this, child: widget.child); | |
| } | |
| Object? get(Object key) => data[key]; | |
| void set(Object key, Object value) { | |
| if (data[key] != value) { | |
| setState(() { | |
| data = Map.from(data); | |
| data[key] = value; | |
| }); | |
| } | |
| } | |
| } | |
| class _AppModelData extends InheritedModel<Object> { | |
| _AppModelData({ | |
| Key? key, | |
| required this.appModelState, | |
| required Widget child | |
| }) : data = appModelState.data, super(key: key, child: child); | |
| final _AppModelState appModelState; | |
| final Map<Object, Object> data; | |
| @override | |
| bool updateShouldNotify(_AppModelData old) { | |
| return data != old.data; | |
| } | |
| @override | |
| bool updateShouldNotifyDependent(_AppModelData old, Set<Object> keys) { | |
| for (Object key in keys) { | |
| if (data[key] != old.data[key]) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| } | |
| // Displays the value of AppModel.get(context, appModelKey) and the number of times | |
| // that this widget has been built. | |
| class ShowAppModelValue extends StatefulWidget { | |
| const ShowAppModelValue(this.appModelKey); | |
| final Object appModelKey; | |
| @override | |
| _ShowAppModelValueState createState() => _ShowAppModelValueState(); | |
| } | |
| class _ShowAppModelValueState extends State<ShowAppModelValue> { | |
| int _buildCount = 0; | |
| @override | |
| Widget build(BuildContext context) { | |
| _buildCount += 1; | |
| return Padding( | |
| padding: EdgeInsets.only(bottom: 16), | |
| child: Text('${widget.appModelKey}: ${AppModel.get(context, widget.appModelKey)} [$_buildCount]'), | |
| ); | |
| } | |
| } | |
| // Demonstrates that changes to the AppModel _only_ cause the dependent widgets | |
| // to be rebuilt. | |
| class Home extends StatefulWidget { | |
| @override | |
| _HomeState createState() => _HomeState(); | |
| } | |
| class _HomeState extends State<Home> { | |
| int _fooCount = 0; | |
| int _barCount = 0; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| body: Center( | |
| child: Column( | |
| mainAxisSize: MainAxisSize.min, | |
| children: <Widget>[ | |
| ShowAppModelValue('Home'), // Only built when the app is launched | |
| ShowAppModelValue('foo'), // Built each time the foo button is pressed | |
| ShowAppModelValue('bar'), // Built each time the bar button is pressed | |
| ElevatedButton( | |
| child: Text('foo = FOO'), | |
| onPressed: () { | |
| _fooCount += 1; | |
| AppModel.set(context, 'foo', 'FOO $_fooCount'); // note: no setState() | |
| }, | |
| ), | |
| SizedBox(height: 16), | |
| ElevatedButton( | |
| child: Text('bar = BAR'), | |
| onPressed: () { | |
| _barCount += 1; | |
| AppModel.set(context, 'bar', 'BAR $_barCount'); // note: no setState() | |
| }, | |
| ), | |
| ], | |
| ), | |
| ), | |
| ); | |
| } | |
| } | |
| void main() { | |
| runApp( | |
| AppModel(child: MaterialApp(home: Home())), | |
| ); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment