Bloc Pattern을 단순한 구조로 만들어주는 Provider Pattern.
1. CountProvider.dart
import "package:flutter/material.dart";
class CountProvider extends ChangeNotifier {
int _count = 0;
int get count => _count;
void plus() {
_count++;
notifyListeners();
}
void minus() {
_count--;
notifyListeners();
}
}
import "package:flutter/foundation.dart";
class CountProvider with ChangeNotifier, DiagnosticableTreeMixin {
int _count = 0;
int get count => _count;
void plus() {
_count++;
notifyListeners();
}
void minus() {
_count--;
notifyListeners();
}
/// Makes `Counter` readable inside the devtools by listing all of its properties
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(IntProperty('count', count));
}
}
2. main.dart
import "package:flutter/material.dart";
import "package:provider/provider.dart";
import "package:provider_example/CountProvider.dart";
import "package:provider_example/home.dart";
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Provider Sample",
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity
),
// home: ChangeNotifierProvider(
// create: (BuildContext context) => CountProvider(),
// child: const Home(title: "Provider example"),
// ),
home: MultiProvider(
providers: [
ChangeNotifierProvider(create: (BuildContext context) => CountProvider()),
],
child: const Home(title: "Provider example"),
),
);
}
}
3. home.dart
import "package:flutter/material.dart";
import "package:provider/provider.dart";
import "package:provider_example/CountProvider.dart";
import "package:provider_example/CountView.dart";
class Home extends StatelessWidget {
final String title;
const Home({super.key, required this.title});
@override
Widget build(BuildContext context) {
print("Widget : Home");
// listen: false는 현재 Widget은 Rendering하지 않도록 한다. But 하위 Widget은 여전히 다시 Rendering된다.
// 하위 Widget에서도 Rendering을 방지할려면 하위 Widget에서 Consumer를 사용하면 된다.
CountProvider countProvider =
Provider.of<CountProvider>(context, listen: false);
return Scaffold(
appBar: AppBar(title: Text(title)),
body: const CountView(),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
IconButton(
onPressed: () => countProvider.plus(),
icon: const Icon(Icons.add)),
IconButton(
onPressed: () => countProvider.minus(),
icon: const Icon(Icons.remove))
],
),
);
}
}
import "package:flutter/material.dart";
import "package:provider/provider.dart";
import "package:provider_example/CountProvider.dart";
import "package:provider_example/CountView.dart";
class Home extends StatelessWidget {
final String title;
const Home({super.key, required this.title});
@override
Widget build(BuildContext context) {
print("Widget : Home");
// listen: false는 현재 Widget은 Rendering하지 않도록 한다. But 하위 Widget은 여전히 다시 Rendering된다.
// 하위 Widget에서도 Rendering을 방지할려면 하위 Widget에서 Consumer를 사용하면 된다.
// CountProvider countProvider =
// Provider.of<CountProvider>(context, listen: false);
return Scaffold(
appBar: AppBar(title: Text(title)),
body: const CountView(),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
IconButton(
//onPressed: () => countProvider.plus(),
/// Calls `context.read` instead of `context.watch` so that it does not rebuild
/// when [CountProvider] changes.
onPressed: () => context.read<CountProvider>().plus(),
icon: const Icon(Icons.add)),
IconButton(
//onPressed: () => countProvider.minus(),
/// Calls `context.read` instead of `context.watch` so that it does not rebuild
/// when [CountProvider] changes.
onPressed: () => context.read<CountProvider>().minus(),
icon: const Icon(Icons.remove))
],
),
);
}
}
4. CountView.dart
import "package:flutter/material.dart";
import "package:provider/provider.dart";
import "package:provider_example/CountProvider.dart";
class CountView extends StatelessWidget {
const CountView({super.key});
@override
Widget build(BuildContext context) {
print("Widget : CountView");
return Center(
// 현재 Widget을 반복하여 Rendering한다.
// child: Text(
// Provider.of<CountProvider>(context).count.toString(),
// style: const TextStyle(fontSize: 80),
// ),
// 현재 Widget을 반복하여 Rendering하지 않는다.
child: Consumer<CountProvider>(builder: (context, provider, child) {
return Text(
provider.count.toString(),
style: const TextStyle(fontSize: 80),
);
}),
);
}
}
import "package:flutter/material.dart";
import "package:provider/provider.dart";
import "package:provider_example/CountProvider.dart";
class CountView extends StatelessWidget {
const CountView({super.key});
@override
Widget build(BuildContext context) {
print("Widget : CountView");
return Center(
// 현재 Widget을 반복하여 Rendering한다.
// child: Text(
// Provider.of<CountProvider>(context).count.toString(),
// style: const TextStyle(fontSize: 80),
// ),
// 현재 Widget을 반복하여 Rendering하지 않는다.
// child: Consumer<CountProvider>(builder: (context, provider, child) {
// return Text(
// provider.count.toString(),
// style: const TextStyle(fontSize: 80),
// );
// }),
/// Calls `context.watch` to make [Count] rebuild when [Counter] changes.
child: Text(
context.watch<CountProvider>().count.toString(),
style: const TextStyle(fontSize: 80),
),
);
}
}