PropertyBuilder

FutureBuilderStreamBuilder是很棒的小部件,它们可以对应用程序状态的异步更改做出反应。 但是,它们仅在更改时触发,并且如果等待的值在构建器准备好之前到达,则丢失。

因此,人们经常使用RX BehaviorSubject 。 但是,如果您不想依赖RX,则以下类将提供相同的行为,而无需其他库。

Property封装一个值并提供从当前值开始的更改流。 您还可以随时读取和写入该值。

这是它的实现:

  import'dart:async'; class Property  { 
StreamController _controller;
T _value; T get value => _value; set value(T newValue){
如果(_value!= newValue){
_value = newValue;
_controller.add(newValue);
}
} Stream 获取流=> _controller.stream; Property(T initialValue){
_value = initialValue;
_controller = StreamController.broadcast(
同步:是的,
onListen:()=> _controller.add(_value),
);
}
}

这是一个如何使用Property实例的示例:

 最终p =属性(42); 
打印(p.value); //显示“ 42”
p。值+ = 1;
打印(p.value); //打印“ 43” p.stream.listen((v)=> print(v)); //再次打印“ 43”。
p。值-= 1; //由于上面的侦听器,输出“ 42”

为了减少使用Property实例时的样板代码,我们还将创建一个类似于StreamBuilder 。 它需要一个property和一个生成builder作为参数。 后者是一个获取通常BuildContext以及当前属性value的函数,并且必须返回Widget

因为Property始终具有当前值,所以永远不会在没有数据的情况下调用builder 。 此外,属性stream永远不会引发错误。 因此,构建器的实现要简单得多。

这是实现:

  class PropertyBuilder 扩展StreamBuilder  { 
PropertyBuilder({
关键
@required Property 属性,
@required Widget Function(BuildContext,T)构建器,
}:super(
键:键,
流:property.stream,
initialData:property.value,
生成器:(上下文,快照){
断言(snapshot.hasData);
assert(!snapshot.hasError);
返回builder(context,snapshot.data);
},
);
}

反例

最后但并非最不重要的是,这是使用PropertyPropertyBuilder实现的常规Flutter计数器示例:

 最终计数器= Property(0);类MyApp扩展了StatelessWidget { 
@override
小部件build(BuildContext context){
返回MaterialApp(
家:脚手架(
身体:中心(
子级:Row(
mainAxisSize:MainAxisSize.min,
子代: [
FloatingActionButton(
onPressed:()=> counter.value--,
子代:Icon(Icons.remove),
海拔:0,
),
PropertyBuilder (
物业:柜台,
生成器:(上下文,快照){
返回文字(
“ $ {counter.value}”,
样式:Theme.of(context).textTheme.display4,
);
},
),
FloatingActionButton(
onPressed:()=> counter.value ++,
子级:Icon(Icons.add),
海拔:0,
),
],
),
),
),
);
}
}

当然, counter属性应与BLoC模式一起使用,而不是使用全局对象。 但这是另一天的故事。