为 ChangeNotifier
提供的ListenableProvider
规范,会在需要时自动调用 ChangeNotifier.dispose
provider: ^6.0.2
ChangeNotifierProvider
:负责监听模型变化从而通知Consumer
ChangeNotifier
:模型类,状态发生改变时调用notifyListeners()
Consumer
:消费者类,收到通知负责重构UIChangeNotifier
notifyListeners()
因为模型类使用了ChangeNotifier
,当我们需要更改某个状态的时候就可以调用notifyListeners()
,并且在调用它的任何时候,ChangeNotifierProvider
都会收到通知并且Consumer
消费者将重建UI。
class NotifierCounter with ChangeNotifier {
int count = 0;
void increment() {
count++;
_notification();
}
void decrement() {
count--;
_notification();
}
void _notification() {
notifyListeners();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Provider Demo')),
body: ChangeNotifierProvider(
lazy: true,
create: (BuildContext context) => NotifierCounter(),
child: const ProvidersDemo(),
),
);
}
Consumer(
builder: (BuildContext context, NotifierCounter counter, child) {
return Text('${counter.count}',
style: const TextStyle(fontSize: 45));
},
),
context.read<NotifierCounter>().increment();
或者:
Provider.of<NotifierCounter>(context, listen: false).increment()
-----------------------
read,listen: false 表示不会监听状态改变(Consumer会监听)
context.watch<T>(),widget 能够监听到 T 类型的 provider 发生的改变。(如果不
使用Consumer限定监听范围会导致刷新范围过大)
context.select<T,R>(R cb(T value)),允许 widget 只监听 T 上的一部分内容的改变。
需要注意的是
context
必须是ChangeNotifierProvider
的context
,如果此时的context
不是ChangeNotifierProvider
的可以使用Builder widget
包裹ChangeNotifierProvider
下的根widget
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (BuildContext context) => NotifierCounter(),
child: Builder(
builder: (context) =>Column(
...
void main() => runApp(const MaterialApp(home: SimpleApp()));
class SimpleApp extends StatelessWidget {
const SimpleApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Provider Demo')),
body: ChangeNotifierProvider(
lazy: true,
create: (BuildContext context) => NotifierCounter(),
child: const ProvidersDemo(),
),
);
}
}
class ProvidersDemo extends StatelessWidget {
const ProvidersDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
const Text('Counter',
style: TextStyle(fontSize: 34, fontWeight: FontWeight.bold)),
Consumer(
builder: (BuildContext context, NotifierCounter counter, child) {
return Text('${counter.count}',
style: const TextStyle(fontSize: 45));
},
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton.icon(
onPressed: () => context.read<NotifierCounter>().increment(),
label: const Text('increment'),
icon: const Icon(Icons.add)),
TextButton.icon(
onPressed: () => context.read<NotifierCounter>().decrement(),
label: const Text('decrement'),
icon: const Icon(Icons.remove))
],
)
]),
);
}
}