flutter开发实战-ValueListenableBuilder实现局部刷新功能
在创建的新工程中,点击按钮更新counter后,通过setState可以出发本类的build方法进行更新。当我们只需要更新一小部分控件的时候,通过setState就不太合适了,这就需要进行局部更新,可以通过provider等状态管理库来实现。当然flutter为我们提供了ValueListenableBuilder来实现局部控件的刷新。
一、ValueListenableBuilder
ValueListenableBuilder的属性如下
const ValueListenableBuilder({
super.key,
required this.valueListenable,
required this.builder,
this.child,
}) : assert(valueListenable != null),
assert(builder != null);
- ValueListenable继承自Listenable,是一个可监听对象。
- builder是一个typedef
typedef ValueWidgetBuilder = Widget Function(BuildContext context, T value, Widget? child); - child,可选,可为空
查看ValueListenableBuilder类的实现可以看到
class _ValueListenableBuilderState<T> extends State<ValueListenableBuilder<T>> {
late T value;
@override
void initState() {
super.initState();
value = widget.valueListenable.value;
widget.valueListenable.addListener(_valueChanged);
}
@override
void didUpdateWidget(ValueListenableBuilder<T> oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.valueListenable != widget.valueListenable) {
oldWidget.valueListenable.removeListener(_valueChanged);
value = widget.valueListenable.value;
widget.valueListenable.addListener(_valueChanged);
}
}
@override
void dispose() {
widget.valueListenable.removeListener(_valueChanged);
super.dispose();
}
void _valueChanged() {
setState(() { value = widget.valueListenable.value; });
}
@override
Widget build(BuildContext context) {
return widget.builder(context, value, widget.child);
}
}
在initState中对传入的可监听对象进行监听,执行_valueChanged方法,_valueChanged执行了setState来触发当前状态的刷新。我们知道setState会执行build方法,触发执行build方法,最总触发widget.builder回调,这样就实现了局部刷新。
child的作用也是非常重要的,我们将Widget放到child中,在执行builder时,会直接使用child,将不会再构建一遍child。
二、ValueListenableBuilder实现局部刷新示例
下面使用ValueListenableBuilder来实现一个局部刷新的示例。示例中,在界面中,有一个显示按钮与隐藏按钮控制修改isShowNotifier的value。通过ValueListenableBuilder的builder中来判断需要显示的内容。
示例代码如下
import 'package:flutter/material.dart';
class ValueListenablePage extends StatefulWidget {
const ValueListenablePage({super.key});
@override
State<ValueListenablePage> createState() => _ValueListenablePageState();
}
class _ValueListenablePageState extends State<ValueListenablePage> {
final isShowNotifier = ValueNotifier<bool>(false);
@override
void initState() {
// TODO: implement initState
super.initState();
}
void show() {
isShowNotifier.value = true;
}
void hide() {
isShowNotifier.value = false;
}
@override
void dispose() {
// TODO: implement dispose
isShowNotifier.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: const Text('ValueListenablePage'),
),
body: Container(
width: screenSize.width,
height: screenSize.height,
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
top: 50,
child: buildValueListenable(context),
),
Positioned(
top: 200,
child: buildButton(context),
),
],
),
),
);
}
Widget buildHide(BuildContext context) {
return Container(
color: Colors.green,
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 50),
child: Text(
"当前隐藏",
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
softWrap: true,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
fontStyle: FontStyle.italic,
color: Colors.white,
decoration: TextDecoration.none,
),
),
);
}
Widget buildValueListenable(BuildContext context) {
return ValueListenableBuilder(
valueListenable: isShowNotifier,
builder: (BuildContext aContext, bool isShow, Widget? child) {
if (isShow) {
return child ?? buildHide(context);
} else {
return buildHide(context);
}
},
child: Container(
color: Colors.blueGrey,
padding: EdgeInsets.symmetric(vertical: 50, horizontal: 50),
child: Text(
"ValueListenableBuilder Child",
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
softWrap: true,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
fontStyle: FontStyle.italic,
color: Colors.white,
decoration: TextDecoration.none,
),
),
),
);
}
Widget buildButton(BuildContext context) {
return Container(
width: 300,
height: 220,
color: Colors.deepOrange,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextButton(
onPressed: () {
show();
},
child: Container(
height: 50,
width: 200,
color: Colors.lightBlue,
alignment: Alignment.center,
child: Text(
'点击显示',
style: TextStyle(
fontSize: 14,
color: Colors.white,
),
),
),
),
TextButton(
onPressed: () {
hide();
},
child: Container(
height: 50,
width: 200,
color: Colors.lightBlue,
alignment: Alignment.center,
child: Text(
'点击隐藏',
style: TextStyle(
fontSize: 14,
color: Colors.white,
),
),
),
),
],
),
);
}
}
效果图如下
三、小结
flutter开发实战-ValueListenableBuilder实现局部刷新功能
学习记录,每天不停进步。