Presenting Streams in Flutter小技巧
程序员界的小学生 人气:0正文
如果我想要做一个组件,每秒更新时间, 最开始的想法就是使用StatefulWidget, 然后每秒调用一下setState方法刷新数据
能不能换成使用StatelessWidget呢? 可以的,不过用Stream来实现。
先创建一个AsyncSnapshot的拓展
extends PresentAsyncSnapshot<E> on AsyncSnapshot<E> { Widget present({ required BuildContext context, Widget Function(BuildContext context)? onNone, Widget Function(BuildContext context, E data)? onData, Widget Function(BuildContext context, Object error, StackTrace stackTrace)? onError, Widget Function(BuildContext context)? onDoneWitNeitherDataNorError, Widget FUnction(BuildContext context)? onWaiting, }) { switch (connectionState) { case ConnectionState.none: return onNone?.call(context) ?? const SizedBox.shrink(); case ConnectionState.waiting: return onWaiting?.call(context) ?? const CircularProgressIndicator(); case ConnectionState.active: //future在done状态产生值,但是stream在active状态下就已经持续产生值了 case ConnectionState.done: if (hasError) { return onError?.call(context, error!, stackTrace!) ?? const SizedBox.shrink(); } else if (hasData) { return onData?.call(context, data as E) ?? const SizedBox.shrink(); } else { reutrn onDoneWitNeitherDataNorError?.call(context) ?? const SizedBox.shrink(); } } } }
创建一个stream,每秒产生一个值
Stream<String> getDataTime() => Stream.perioodic( const Duration(seconds: 1), (_) => DateTime.now().toIso8601string(), );
创建Stream拓展
为了方便使用,我又创建了一个Stream的拓展,为了内部使用上面写的PresentAsyncSnapshot拓展
extension PresentStream<E> on Stream<E> { Widget present({ Widget Function(BuildContext context)? onNone, Widget Function(BuildContext context, E data)? onData, Widget Function(BuildContext context, Object error, E data)? onData, Widget Function(BuildContext context)? onDoneWitNeitherDataNorError, Widget Function(BuildContext context)? onWaiting. }) { return StreamBuilder<E>( stream: this, builder: (context, snapshot) => snapshot.present( context: context, onNone: onNone, onData: onData, onError: onError, onDoneWitNeitherDataNorError: onDoneWItNeitherDataNorError, onWaiting: onWaiting, ), ); } }
下面来测试一下,只需要在任何Stream的地方 调用present()就能很简单的使用,可以传入你想要调用的任何方法的回调。
class HomePage extends StatelessWidget { const HomePage({Key? key}): super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: getDateTime().present( onData: (_, dateTime) => Text(dateTime), ), ), ); } }
大功告成,下面看一下结果
加载全部内容