flutter数据监听器
Categories:
flutter
最近用Flutter做功能的时候,发现了这么一个控件ValueListenableBuilder
,它也是一个Widget,从它的名字看应该是监听数据,并且用新的数据生成Widget,它的参数就三个:
const ValueListenableBuilder({
@required this.valueListenable,
@required this.builder,
this.child,
})
参数说明
- valueListenable 数据监听,官方说明:This interface is implemented by [ValueNotifier
] and [Animation ],所以它不仅可以是ValueNotifier,还可以是Animation。 - builder 根据上面的监听器重新绘制Widget。
- child 这个child会作为参数传入上面的那个builder方法中,它干啥用呢。可能ValueListenableBuilder生成的Widget中有一些子元素跟上面监听的数据没有关系,不需要重新绘制。
示例
从上面那些说明看来这个控件的作用就是作为局部刷新用的,可能我们整个页面上只是一个小参数变化了,那有了这个Widget就不需要用setState(() {});
来刷新整个页面。
做个简单的示例,这个示例是flutter默认生成的项目改写的:
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
final ValueNotifier<int> _notifier = ValueNotifier<int>(0);
void _incrementCounter() {
_counter++;
_notifier.value++;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ValueListenableBuilder(
valueListenable: _notifier,
builder: (BuildContext context, int value, Widget child) {
return Text(
'You have pushed the button this many times:$value',
);
}),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
_incrementCounter
函数的代码,在点击按钮的时候,没有执行setState(() {});
,但是ValueListenableBuilder
内的Text的数字却变化了,而原来的外面的那个Text上的数字没有变化。
示例2
上面的例子监听了一个int类型,这次用一个复杂对象,顺便试试一下child
参数。
先看图:
复杂对象😄:
class ComplicatedObject {
int number;
String title;
ComplicatedObject({this.number, this.title});
}
示例代码:
class _MyHomePageState extends State<MyHomePage> {
final ValueNotifier<ComplicatedObject> _notifier =
ValueNotifier<ComplicatedObject>(
ComplicatedObject(number: 0, title: '标题'));
//中间不变的内容
Widget _content;
void _incrementCounter() {
_notifier.value = ComplicatedObject(number: 1024, title: '新标题');
}
@override
void initState() {
_content = Center(
child: Text(
'这里是内容。。。。。。。。。。。。。',
));
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ValueListenableBuilder(
valueListenable: _notifier,
builder: (BuildContext context, ComplicatedObject value, Widget child) {
return Column(
children: <Widget>[
Container(
height: 48,
child: Text('${value.title}',
style: Theme.of(context).textTheme.display1),
),
Expanded(
child: child,
flex: 1,
),
Container(
height: 48,
child: Text('${value.number}',
style: Theme.of(context).textTheme.caption),
),
],
);
},
child: _content,//这里是传入上面生成好的不变的Widget
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
自定义监听对象属性
既然复杂对象可以监听,那肯定有些需求说是我只想监听这个对象中的某些属性怎么办,这可以通过重写ValueNotifier对象实现:
class ComplicatedObjectNotifier extends ValueNotifier<ComplicatedObject> {
ComplicatedObjectNotifier(ComplicatedObject object): super(object);
void setTitle(String newTitle) {
value.title = newTitle;
//这句是关键 一定要写。
notifyListeners();
}
}
有了这个重写的类,把原来代码中的ValueNotifier替换掉:
class _MyHomePageState extends State<MyHomePage> {
final ComplicatedObjectNotifier _notifier =
ComplicatedObjectNotifier(
ComplicatedObject(number: 0, title: '标题'));
//中间不变的内容
Widget _content;
void _incrementCounter() {
_notifier.setTitle('又是新标题');
}
@override
void initState() {
_content = Center(
child: Text(
'这里是内容。。。。。。。。。。。。。',
));
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ValueListenableBuilder(
valueListenable: _notifier,
builder: (BuildContext context, ComplicatedObject value, Widget child) {
return Column(
children: <Widget>[
Container(
height: 48,
child: Text('${value.title}',
style: Theme.of(context).textTheme.display1),
),
Expanded(
child: child,
flex: 1,
),
Container(
height: 48,
child: Text('${value.number}',
style: Theme.of(context).textTheme.caption),
),
],
);
},
child: _content,//这里是传入上面生成好的不变的Widget
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
结果就是这样了:
还是那句老话Flutter给我们提供了很多好玩好看又好用的Widget,对于一个开发者而言,真是太友好了!
The End !