Documentation Updated
1 |
// ignore_for_file: public_member_api_docs, lines_longer_than_80_chars
|
|
2 |
import 'package:flutter/foundation.dart'; |
|
3 |
import 'package:flutter/material.dart'; |
|
4 |
import 'package:provider/provider.dart'; |
|
5 |
|
|
6 |
/// This is a reimplementation of the default Flutter application using provider + [ChangeNotifier].
|
|
7 |
|
|
8 | 3 |
void main() { |
9 | 3 |
runApp( |
10 |
/// Providers are above [MyApp] instead of inside it, so that tests
|
|
11 |
/// can use [MyApp] while mocking the providers
|
|
12 | 3 |
MultiProvider( |
13 | 3 |
providers: [ |
14 | 3 |
ChangeNotifierProvider(create: (_) => Counter()), |
15 |
],
|
|
16 | 3 |
child: MyApp(), |
17 |
),
|
|
18 |
);
|
|
19 |
}
|
|
20 |
|
|
21 |
/// Mix-in [DiagnosticableTreeMixin] to have access to [debugFillProperties] for the devtool
|
|
22 |
class Counter with ChangeNotifier, DiagnosticableTreeMixin { |
|
23 |
int _count = 0; |
|
24 | 3 |
int get count => _count; |
25 |
|
|
26 | 3 |
void increment() { |
27 | 3 |
_count++; |
28 | 3 |
notifyListeners(); |
29 |
}
|
|
30 |
|
|
31 |
/// Makes `Counter` readable inside the devtools by listing all of its properties
|
|
32 | 3 |
@override |
33 |
void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
|
34 | 3 |
super.debugFillProperties(properties); |
35 | 3 |
properties.add(IntProperty('count', count)); |
36 |
}
|
|
37 |
}
|
|
38 |
|
|
39 |
class MyApp extends StatelessWidget { |
|
40 | 3 |
@override |
41 |
Widget build(BuildContext context) { |
|
42 |
return const MaterialApp( |
|
43 |
home: MyHomePage(), |
|
44 |
);
|
|
45 |
}
|
|
46 |
}
|
|
47 |
|
|
48 |
class MyHomePage extends StatelessWidget { |
|
49 | 3 |
const MyHomePage({Key key}) : super(key: key); |
50 |
|
|
51 | 3 |
@override |
52 |
Widget build(BuildContext context) { |
|
53 | 3 |
return Scaffold( |
54 | 3 |
appBar: AppBar( |
55 |
title: const Text('Example'), |
|
56 |
),
|
|
57 | 3 |
body: Center( |
58 | 3 |
child: Column( |
59 |
mainAxisSize: MainAxisSize.min, |
|
60 |
mainAxisAlignment: MainAxisAlignment.center, |
|
61 | 3 |
children: <Widget>[ |
62 |
const Text('You have pushed the button this many times:'), |
|
63 |
|
|
64 |
/// Extracted as a separate widget for performance optimization.
|
|
65 |
/// As a separate widget, it will rebuild independently from [MyHomePage].
|
|
66 |
///
|
|
67 |
/// This is totally optional (and rarely needed).
|
|
68 |
/// Similarly, we could also use [Consumer] or [Selector].
|
|
69 |
const Count(), |
|
70 |
],
|
|
71 |
),
|
|
72 |
),
|
|
73 | 3 |
floatingActionButton: FloatingActionButton( |
74 |
/// Calls `context.read` instead of `context.watch` so that it does not rebuild
|
|
75 |
/// when [Counter] changes.
|
|
76 | 3 |
onPressed: () => context.read<Counter>().increment(), |
77 |
tooltip: 'Increment', |
|
78 |
child: const Icon(Icons.add), |
|
79 |
),
|
|
80 |
);
|
|
81 |
}
|
|
82 |
}
|
|
83 |
|
|
84 |
class Count extends StatelessWidget { |
|
85 | 3 |
const Count({Key key}) : super(key: key); |
86 |
|
|
87 | 3 |
@override |
88 |
Widget build(BuildContext context) { |
|
89 | 3 |
return Text( |
90 |
|
|
91 |
/// Calls `context.watch` to make [MyHomePage] rebuild when [Counter] changes.
|
|
92 | 3 |
'${context.watch<Counter>().count}', |
93 | 3 |
style: Theme.of(context).textTheme.headline4); |
94 |
}
|
|
95 |
}
|
Read our documentation on viewing source code .