Flutter&Bedrock框架——页面的局部刷新介绍
2020-11-27 本文已影响0人
10块钱new一个对象
常见的Widget刷新
一般在flutter中刷新widget,最常用的是通过方法
setState()

举个栗子,有页面如下

伪-代码如下:
build(){
debugPrint('page build');
return Column(children: [
//上方按钮
btnAbove(),
// 两个色块
row(children:[红色、蓝色])
//下方按钮
btnBelow(),
//色块 widget
DoubleColorWidget(),
]);
}
//
class DoubleColorWidget{
build(){
debugPrint('DoubleColorWidget build');
return row(children:[红色、蓝色]);
}
}

当我点击上方的按钮以交换毗邻的两个方块的颜色时,通过log可以发现,页面和DoubleColorWidget 都执行了一遍build()方法。
每点一次都会执行,且DoubleColorWidget(并不需要刷新)也触发了 build


页面简单的话,也许可以忽略,如果页面比较复杂,那么大量的无意义build()将会带来性能的损耗。
一般情况下,我们可以通过各种状态控制工具,如:
Bloc,redux,fish-redux,Provider等等

也可以为子widget写一个控制器,并对外暴露。
还可以用flutter自带的inheritWidget或各种Builder,如最简单的statefulWidgetBuilder,对需要刷新的widget进行包裹,并单独rebuild。
与此同时就会额外增加不少代码,尤其是页面中需要独立刷新的widget非常多时(实际开发中,这基本难以避免)。
这里我向大家介绍一下Bedrock框架下的刷新方法。
基于Bedrock的widget刷新
首先Bedrock对于上方提到的刷新依然支持,同时借助框架的设计:
在减少代码的同时,支持直接调用widget的方法,进而完成任意粒度的局部刷新(等各种操作),以下是更改后的页面代码:
class PartRefreshPage extends PageState{
bool exp1 = false;
///下方色块
final PartWidget partWidget = PartWidget();
@override
Widget build(BuildContext context) {
debugPrint('page build');
return switchStatusBar2Dark(child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
///上方按钮
RaisedButton(onPressed: (){
exp1 = !exp1;
setState(() {
});
},
child: Text('change color By setState()'),),
///上方色块
Container(
height: getWidthPx(100),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: getWidthPx(80),
color: exp1 ? Colors.red:Colors.blue,
),
Container(
width: getWidthPx(80),
color: exp1 ? Colors.blue:Colors.red,
),
],
),
),
getSizeBox(height: getWidthPx(100)),
///-----------下方代码区域-----------
///下方按钮
RaisedButton(onPressed: (){
partWidget.switchColor();
},
child: Text('change color By part refresh'),),
///下方色块
partWidget.generateWidget(),
],
),
));
}
}
class PartWidget extends WidgetState{
bool exp1 = false;
///此为Demo 故,书写随意
void switchColor(){
if(!mounted)return;
exp1 = !exp1;
setState(() {
});
}
@override
Widget build(BuildContext context) {
debugPrint('DoubleColorWidget build');
return Container(
height: getWidthPx(100),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: getWidthPx(80),
color: exp1 ? Colors.red:Colors.blue,
),
Container(
width: getWidthPx(80),
color: exp1 ? Colors.blue:Colors.red,
),
],
),
);
}
}

我们可以看到,在‘下方’代码区域中,下方按钮如果想交换其下方两个色块的颜色,只需要直接调用它的switchColor(),同时不会触发无关widget和页面的build方法。
另外,因为state对外暴露,我们在处理widget上,变得更为灵活方便。
谢谢大家的阅读,如有错误,还请指出,谢谢。