Flutter StatefulBuilder实现局部刷新
前言
flutter项目中,在页面数据较多的情况下使用全量刷新对性能消耗较大且容易出现短暂白屏的现象,出于性能和用户体验方面的考虑我们经常会使用局部刷新代替全量刷新进行页面更新操作。
GlobalKey
、ValueNotifier
和StreamBuilder
等技术方案都可以实现Flutter页面的局部刷新,本文主要记录的是通过StatefulBuilder
组件来实现局部刷新的方法。
页面的全量刷新
在StatefulWidget
内直接调用setState
方法更新数据时,会导致页面重新执行build
方法,使得页面被全量刷新。
我们可以通过以下案例了解页面的刷新情况:
int a = 0;
int b = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 点击按钮,数据‘a’加1,并刷新页面
ElevatedButton(
onPressed: () {
a++;
setState(() {});
},
child: Text('a : $a'),
),
// 点击按钮,数据‘b’加1,并刷新页面
ElevatedButton(
onPressed: () {
b++;
setState(() {});
},
child: Text('b : $b'),
),
],
),
),
);
}
代码运行效果如图:
当我们点击第一个ElevatedButton
组件时,会执行a++
和setState(() {})
语句。通过系统的Flutter Performance工具我们可以捕获到组件刷新的情况,当执行到setState(() {})
时,页面不只是刷新a
数据所在的ElevatedButton
组件,而是重新构建了页面,这会造成额外的性能消耗。
出于性能的考虑,我们更希望当点击第一个ElevatedButton
组件时,系统只对a
数据进行更新,b
作为局外人不参与此次活动。我们可以通过StatefulBuilder
组件来实现这个功能。
StatefulBuilder简介
StatefulBuilder
组件包含了两个参数,其中builder
参数为必传,不能为空:
const StatefulBuilder({
Key? key,
required this.builder,
}) : assert(builder != null),
super(key: key);
builder
包含了两个参数,一个页面的context,另一个是用于状态改变时触发重建的方法:
typedef StatefulWidgetBuilder = Widget Function(BuildContext context, StateSetter setState);
final StatefulWidgetBuilder builder;
StatefulBuilder的实际应用
StatefulBuilder
组件在实际应用中主要分成以下操作:
1、定义一个
StateSetter
类型的方法;2、将需要局部刷新数据的组件嵌套在
StatefulBuilder
组件内;3、调用第1步定义的
StateSetter
类型方法对StatefulBuilder
内部进行刷新;
int a = 0;
int b = 0;
// 1、定义一个叫做“aState”的StateSetter类型方法;
StateSetter? aState;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// 2、将第一个“ElevatedButton”组件嵌套在“StatefulBuilder”组件内;
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
aState = setState;
return ElevatedButton(
onPressed: () {
a++;
// 3、调用“aState”方法对“StatefulBuilder”内部进行刷新;
aState(() {});
},
child: Text('a : $a'),
);
},
),
ElevatedButton(
onPressed: () {
b++;
setState(() {});
},
child: Text('b : $b'),
),
],
),
),
);
}
重新运行后点击第一个按钮对a
进行累加时,通过Flutter Performance工具我们可以了解到,只有StatefulBuilder
组件及其包含的组件被重新构建,实现了局部刷新的功能,有效的提高了页面的性能;
总结
StatefulWidget
内更新一个属性会导致整个树重新构建,为防止这种不必要的性能消耗,可以通过StatefulBuilder
组件进行局部刷新,有效的提高性能。
作者:zheng1998
链接:https://juejin.cn/post/7134335466614030344
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。