mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 13:58:47 +00:00
After this change, we’re managing Counter’s lifecycle with ChangeNotifierProvider. This removes the periodic Timer. Not only does that simplify the example and makes it closer to the original, it also prevents a leaking timer (though, in this case, it’s not an issue, since the timer is needed for the whole duration of the app). I experimented with a more robust approach (having or injecting a Timer/StreamController into the Counter, and disposing of it there) but that seemed overly complex for such a simple example. This whole problem will get significantly easier with https://github.com/rrousselGit/provider/issues/46, at which point I could reintroduce this. I will also think about a more complex Provider example, something like the venerable `bloc_complex`, with infinite-scrolling pagination and all that.
91 lines
2.9 KiB
Dart
91 lines
2.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
void main() {
|
|
runApp(
|
|
// Provide the model to all widgets within the app. We're using
|
|
// ChangeNotifierProvider because that's a simple way to rebuild
|
|
// widgets when a model changes. We could also just use
|
|
// Provider, but then we would have to listen to Counter ourselves.
|
|
//
|
|
// Read Provider's docs to learn about all the available providers.
|
|
ChangeNotifierProvider(
|
|
// Initialize the model in the builder. That way, Provider
|
|
// can own Counter's lifecycle, making sure to call `dispose`
|
|
// when not needed anymore.
|
|
builder: (context) => Counter(),
|
|
child: MyApp(),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Simplest possible model, with just one field.
|
|
///
|
|
/// [ChangeNotifier] is a class in `flutter:foundation`. [Counter] does
|
|
/// _not_ depend on Provider.
|
|
class Counter with ChangeNotifier {
|
|
int value = 0;
|
|
|
|
void increment() {
|
|
value += 1;
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
class MyApp extends StatelessWidget {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp(
|
|
title: 'Flutter Demo',
|
|
theme: ThemeData(
|
|
primarySwatch: Colors.blue,
|
|
),
|
|
home: MyHomePage(),
|
|
);
|
|
}
|
|
}
|
|
|
|
class MyHomePage extends StatelessWidget {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text('Flutter Demo Home Page'),
|
|
),
|
|
body: Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: <Widget>[
|
|
Text('You have pushed the button this many times:'),
|
|
// Consumer looks for an ancestor Provider widget
|
|
// and retrieves its model (Counter, in this case).
|
|
// Then it uses that model to build widgets, and will trigger
|
|
// rebuilds if the model is updated.
|
|
Consumer<Counter>(
|
|
builder: (context, counter, child) => Text(
|
|
'${counter.value}',
|
|
style: Theme.of(context).textTheme.display1,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
floatingActionButton: FloatingActionButton(
|
|
// Provider.of is another way to access the model object held
|
|
// by an ancestor Provider. By default, even this listens to
|
|
// changes in the model, and rebuilds the whole encompassing widget
|
|
// when notified.
|
|
//
|
|
// By using `listen: false` below, we are disabling that
|
|
// behavior. We are only calling a function here, and so we don't care
|
|
// about the current value. Without `listen: false`, we'd be rebuilding
|
|
// the whole MyHomePage whenever Counter notifies listeners.
|
|
onPressed: () =>
|
|
Provider.of<Counter>(context, listen: false).increment(),
|
|
tooltip: 'Increment',
|
|
child: Icon(Icons.add),
|
|
),
|
|
);
|
|
}
|
|
}
|