Flutter Tips之 – Presenting Streams in Flutter

如果我想要做一个组件,每秒更新时间,
最开始的想法就是使用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的拓展,为了内部使用上面写的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),
                ),
            ),
        );
    }
}

大功告成,下面看一下结果

ezgif.com-gif-maker.gif

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容