質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

Q&A

解決済

1回答

1642閲覧

BLoCを使って共有のカウントダウンタイマーを別々のページで使いたい。

Inete6Q

総合スコア18

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

0グッド

0クリップ

投稿2020/12/14 08:30

前提・実現したいこと

BLocを使って共通の時間を示すカウントダウンタイマーを別々のページで使いたいと思っています。
コードを単純にすると下記のようなコードのテキスト部分にカウントダウンタイマーを表示させたいです。

dart

1import 'package:flutter/material.dart'; 2 3void main() { 4 runApp(MyApp()); 5} 6 7class MyApp extends StatelessWidget { 8 // This widget is the root of your application. 9 10 Widget build(BuildContext context) { 11 return MaterialApp( 12 13 home: HomePage(), 14 ); 15 16 } 17 18 19 20} 21 22class HomePage extends StatelessWidget { 23 24 Widget build(BuildContext context) { 25 return Scaffold( 26 appBar: AppBar( 27 title: Text('サンプルページ'), 28 ), 29 body: Center( 30 child: Column( 31 children: [ 32 RaisedButton( 33 child: Text('ダイアログ表示'), 34 onPressed: (){ 35 _showDialog(context); 36 } 37 ), 38 Text('このテキスト部分にカウントダウンタイマーを表示させたい') 39 ], 40 ), 41 ), 42 ); 43 } 44 45 46 47 _showDialog(context){ 48 showDialog( 49 context: context, 50 builder: (context){ 51 return AlertDialog( 52 title: Text('sample dialog'), 53 actions: [ 54 RaisedButton( 55 child: Text('次のページへ'), 56 onPressed: (){ 57 Navigator.push( 58 context, 59 MaterialPageRoute(builder: (context) => NextPage()), 60 ); 61 }) 62 ], 63 ); 64 }); 65 } 66} 67 68 69class NextPage extends StatelessWidget { 70 71 Widget build(BuildContext context) { 72 return Scaffold( 73 appBar: AppBar(), 74 body: Center( 75 child: Text('このテキスト部分にカウントダウンタイマーを表示させたい'), 76 ), 77 ); 78 } 79} 80 81

試したこと

リンク内容
この方の記事を読んだりしながら調べていろいろやってみたんですが、Streambuilderを使うのかなと思うのですが、非同期で値を変更しながらどちらで見ても同じ値を取得する方法がわかりません。
ざっくりとした質問で申し訳ないのですが、大まかでもいいので教えてもらいたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

dart

1import 'dart:async'; 2 3import 'package:bloc/bloc.dart'; 4import 'package:flutter/material.dart'; 5import 'package:flutter_bloc/flutter_bloc.dart'; 6 7void main() { 8 runApp(const MyApp()); 9} 10 11enum CounterEvent { decrement, reset } 12 13class CounterBloc extends Bloc<CounterEvent, int> { 14 CounterBloc() : super(10); 15 16 void startCountDown() { 17 Timer.periodic(Duration(seconds: 1), (_) { 18 if (state == 0) { 19 this.add(CounterEvent.reset); 20 } else { 21 this.add(CounterEvent.decrement); 22 } 23 }); 24 } 25 26 27 Stream<int> mapEventToState(CounterEvent event) async* { 28 switch (event) { 29 case CounterEvent.decrement: 30 yield state - 1; 31 break; 32 case CounterEvent.reset: 33 yield 10; 34 break; 35 } 36 } 37} 38 39class MyApp extends StatelessWidget { 40 const MyApp({Key key}) : super(key: key); 41 42 Widget build(BuildContext context) { 43 return BlocProvider( 44 create: (_) => CounterBloc()..startCountDown(), 45 child: MaterialApp( 46 title: 'Blob Timer Demo', 47 theme: ThemeData( 48 primarySwatch: Colors.grey, 49 ), 50 home: HomePage(), 51 )); 52 } 53} 54 55class HomePage extends StatelessWidget { 56 57 Widget build(BuildContext context) => Scaffold( 58 appBar: AppBar( 59 title: Text('サンプルページ'), 60 ), 61 body: Center( 62 child: Column( 63 children: [ 64 RaisedButton( 65 child: Text('ダイアログ表示'), 66 onPressed: () => _showDialog(context)), 67 BlocBuilder<CounterBloc, int>( 68 builder: (context, state) => Text('$state')) 69 ], 70 ), 71 ), 72 ); 73 74 _showDialog(context) => showDialog( 75 context: context, 76 builder: (_) => AlertDialog( 77 title: Text('sample dialog'), 78 actions: [ 79 RaisedButton( 80 child: Text('次のページへ'), 81 onPressed: () { 82 Navigator.of(context).push( 83 MaterialPageRoute(builder: (_) => NextPage()), 84 ); 85 }) 86 ], 87 )); 88} 89 90class NextPage extends StatelessWidget { 91 92 Widget build(BuildContext context) { 93 return Scaffold( 94 appBar: AppBar(), 95 body: Center( 96 child: BlocBuilder<CounterBloc, int>( 97 builder: (context, state) => Text('$state'))), 98 ); 99 } 100}

こうですかね。

気をつけなければならないのは、MaterialAppの下でNavigatorで遷移する場合、何も指定しなければ、MaterialAppの基底のWidgetを入れ替えてしまうという動作を覚えておくことです。

そのため、複数のページで同じProviderから与えられるstateを得るためには、MaterialAppの外側にProviderを配置しなければなりません。

内側でProviderを用いると、Navigatorで遷移した先のPageのbuildの引数となっているBuildContextのインスタンスはMaterialAppの基底のBuildContextであるため、Providerを含まないことになります。

もっとスコープを限定してBlocを用いてStateをPageで共有する場合は、スコープを限定したNavigatorを自分で作る必要があります。この場合、Navigatorが階層化するため複雑になりがちなので、ページ遷移の管理について設計をよく考える必要があります。

投稿2020/12/21 06:27

aya-eiya

総合スコア97

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Inete6Q

2020/12/23 03:36

ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問