[Flutter] カウントダウン機能を Stream + StreamBuilder + Providerで実現する。


Stream とStreamBuilder, Provider を使って、簡単なカウントダウン機能を実現してみます。

StreamController にロジックを書き、WidgetにProviderで流し込んでます。

StreamBuilderを使うことで、データが変わるとこだけリビルドできるので、Statefull Widget の setStateより効率的です。ロジックとViewも分離できます。


class CountdownController {
  CountdownController();

  var _controller = StreamController<int>();
  var _count = 10;
  var _max = 10;
  get stream => _controller.stream; // streamにアクセスできるようにする

  Future<void> countdownStart() async {
    _count = _max;
    while (_count > 0) {
      await Future.delayed(Duration(seconds: 1));
      _count--;
      _controller.add(_count); //データを流す。
    }
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Providerでロジックを注入
    return Provider(
      create: (_) => CountdownController(),
      // 同じ階層ではProviderを使えないためBuilderもしくは別のWidgetに切り出す必要がある。
      child: Builder( 
        builder: (context) => Scaffold(
          body: Center(
            child: StreamBuilder(
              stream: Provider.of<CountdownController>(context).stream,
              // snapShot.dataでstreamを取得する。
              builder: (context, snapShot) {
                if (!snapShot.hasData)
                  return Text("Start Timer");
                else
                  return Text(snapShot.data.toString());
              },
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: Provider.of<CountdownController>(context).countdownStart,
            child: Icon(Icons.play_arrow),
          ),
        ),
      ),
    );
  }
}

最近知ったのですが、BLoCパターンはStreamを使ってロジックとViewを分離するものなんですね。この実装も簡単ですがBLoCもどきということでしょう。

この記事はブログのクロス投稿です。
https://shuent.qrunch.io/entries/jHL5XPzalsNWZbz2