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 12
void main() {
9 12
  runApp(
10
    /// Providers are above [MyApp] instead of inside it, so that tests
11
    /// can use [MyApp] while mocking the providers
12 12
    MultiProvider(
13 12
      providers: [
14 12
        ChangeNotifierProvider(create: (_) => Counter()),
15
      ],
16 12
      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 12
  int get count => _count;
25

26 12
  void increment() {
27 12
    _count++;
28 12
    notifyListeners();
29
  }
30

31
  /// Makes `Counter` readable inside the devtools by listing all of its properties
32 12
  @override
33
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
34 12
    super.debugFillProperties(properties);
35 12
    properties.add(IntProperty('count', count));
36
  }
37
}
38

39
class MyApp extends StatelessWidget {
40 12
  @override
41
  Widget build(BuildContext context) {
42
    return const MaterialApp(
43
      home: MyHomePage(),
44
    );
45
  }
46
}
47

48
class MyHomePage extends StatelessWidget {
49 12
  const MyHomePage({Key key}) : super(key: key);
50

51 12
  @override
52
  Widget build(BuildContext context) {
53 12
    return Scaffold(
54 12
      appBar: AppBar(
55
        title: const Text('Example'),
56
      ),
57 12
      body: Center(
58 12
        child: Column(
59
          mainAxisSize: MainAxisSize.min,
60
          mainAxisAlignment: MainAxisAlignment.center,
61 12
          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 12
      floatingActionButton: FloatingActionButton(
74
        /// Calls `context.read` instead of `context.watch` so that it does not rebuild
75
        /// when [Counter] changes.
76 12
        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 12
  const Count({Key key}) : super(key: key);
86

87 12
  @override
88
  Widget build(BuildContext context) {
89 12
    return Text(
90

91
        /// Calls `context.watch` to make [MyHomePage] rebuild when [Counter] changes.
92 12
        '${context.watch<Counter>().count}',
93 12
        style: Theme.of(context).textTheme.headline4);
94
  }
95
}

Read our documentation on viewing source code .

Loading