一、前言
在Flutter中通常刷新UI是使用setState(() {});
进行刷新,只是这种方式会让UI进行全局刷新,对于比较复杂的页面来说,如果仅仅是改变其中一小部分的UI来说进行刷新是不恰当的,因此官方提供了ValueNotifier
来进行刷新。ValueNotifier
是一个泛型,所以可以传递各种数据。ValueNotifier
不仅仅可以进行单个组件的刷新,也可以同时被多个组件进行监听,还可以对自定义数据进行处理,本文通过一个点击按钮改变数字的功能进行演示。ValueNotifier
其父类为ChangeNotifier
,可以参考以下链接进行了解:
https://blog.csdn.net/Mr_Tony/article/details/112345491
二、单个数据的刷新
void main() => runApp(MyApp());
ValueNotifier<int> _valueNotifier = ValueNotifier<int>(0);//数据监听器
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
appBar: AppBar(
title: Text('Material App Bar'),
),
body: Center(
child: Container(
child: Column(
children: [
ChildWidget1(),
ChildWidget2()
],
),
),
),
),
);
}
}
class ChildWidget1 extends StatefulWidget {
@override
_ChildWidget1State createState() => _ChildWidget1State();
}
class _ChildWidget1State extends State<ChildWidget1> {
@override
Widget build(BuildContext context) {
print('YM---ChildWidget1----进行刷新啊');
return ValueListenableBuilder<int>(
valueListenable: _valueNotifier,
builder: (BuildContext context, int value, Widget child){
print('YM----ChildWidget1-----ValueListenableBuilder----进行刷新啊');
return Text('ChildWidget1新值:$value');
},
// child: Container(
// child: Text('子控件'),
// ),
);
}
}
class ChildWidget2 extends StatefulWidget {
@override
_ChildWidget2State createState() => _ChildWidget2State();
}
class _ChildWidget2State extends State<ChildWidget2> {
@override
Widget build(BuildContext context) {
print('YM---ChildWidget2----进行刷新啊');
return Container(
child: RaisedButton(
onPressed: (){
_valueNotifier.value++;
},
child: Text('点击更改其它地方的数据'),
),
);
}
}
三、多个数据的监听
class ChildWidget3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ValueListenableBuilder<int>(
valueListenable: _valueNotifier,
builder: (BuildContext context, int value, Widget child){
print('YM--ChildWidget3-----ValueListenableBuilder----进行刷新啊');
return Text('ChildWidget3新值:$value');
},
// child: Container(
// child: Text('子控件'),
// ),
);
}
}
...
Column(
children: [
ChildWidget1(),
ChildWidget2(),
ChildWidget3()
],
)
...
四、自定义数据的监听
在实际业务中,通常会定义数据模型,对于单个实例也只是改变里面的数据,因此需要用到自定义ValueNotifier
的方式,通过将上文的int值包装在一个实体类里面来对该功能进行演示
自定义的CounterValueNotifier
如下:
class Counter{
int count = 0;
}
class CounterValueNotifier extends ValueNotifier<Counter>{
CounterValueNotifier(Counter counter):super(counter);
changeCount(){
value.count++;
notifyListeners();
}
}
CounterValueNotifier _counterValueNotifier = CounterValueNotifier(Counter());
修改ValueListenableBuilder
如下:
ValueListenableBuilder<Counter>(
valueListenable: _counterValueNotifier,
builder: (BuildContext context, Counter value, Widget child){
print('YM----ChildWidget1-----ValueListenableBuilder----进行刷新啊');
return Text('ChildWidget1新值:${value.count}');
},
// child: Container(
// child: Text('子控件'),
// ),
)
修改点击事件如下:
RaisedButton(
onPressed: (){
_counterValueNotifier.changeCount();
},
child: Text('点击更改其它地方的数据'),
)
五、参考链接
-
Flutter 组件 | ValueListenableBuilder 局部刷新小能手:
-
Flutter ValueNotifier 异步通信、ValueListenableBuilder异步更新数据:
https://blog.csdn.net/zl18603543572/article/details/109151309