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

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

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

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

Dart

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

Q&A

解決済

1回答

4536閲覧

ChangeNotifierProviderでnotifyListenersで通知した時にUIが更新されない【Flutter】

toshi_ki

総合スコア17

Flutter

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

Dart

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

0グッド

0クリップ

投稿2020/10/17 07:48

編集2020/10/27 03:27

実現したいこと

AppBarのタイトルやボタンをString型やVoidCallbackとしてProviderに保持し、下位のWidgetツリーから変更できるようにしたい。

試したこと

自作のChangeNortifierを継承したAppBarStateクラスをChangeNotifierProviderでcreateしてAppBarState内の値をWidgetで使用しています。

さらに、AppBarState内でsetTitleメソッドを定義していて、メソッド実行時、titleの値を変更してnotifyListners()で通知するようにしています。

ですが、setTitleメソッド実行時にUIが更新されません。

setTitleが呼び出されたあと、HotReloadすると値が変更されます。

setTitleが呼び出された時点で変更を反映させるためにはどうしたらいいのでしょうか。

コードを全て載せると長くなってしまうので、関連する箇所のみコードを載せておきます。

気になるところでもいいので何か分かる方がいましたら、お力添えしていただけるとありがたいです。

よろしくお願いします。

CustomChangeNotifierClass

1class AppBarState extends ChangeNotifier { 2 AppBarState() : hasPreviousPage = false; 3 4 Widget leadButton; 5 VoidCallback leadButtonFunction; 6 bool hasPreviousPage; 7 8 String title = "Title"; 9 10 get leadButtonAction => leadButtonFunction; 11 get appBarTitle => title; 12 13 void setTitle(String value) { 14 title = value; 15 notifyListeners(); 16 } 17 18 void setLeadButton(Widget widget, VoidCallback callback) { 19 leadButton = widget; 20 leadButtonFunction = callback; 21 notifyListeners(); 22 } 23}

CreatingChangeNotifier

1class MyApp extends StatelessWidget { 2 @override 3 Widget build(BuildContext context) { 4 return MultiProvider( 5 providers: [ 6 ChangeNotifierProvider(create: (_) => AppBarState()) 7 ], 8 child: MemberPage(), 9 ); 10 } 11}

UsingValue

1class MemberPage extends StatefulWidget { 2 @override 3 MemberPageState createState() => MemberPageState(); 4} 5 6class MemberPageState extends State<MemberPage> { 7 8 @override 9 Widget build(BuildContext context) { 10 String appBarTitle = Provider.of<AppBarState>(context).appBarTitle; 11 12 return Scaffold( 13 appBar: AppBar( 14 title: Padding( 15 padding: const EdgeInsets.symmetric(horizontal: 20.0), 16 child: Text(appBarTitle), 17 ), 18 ), 19 ... 20 ) 21 } 22}

ChangingValue

1class QuestionDetailList extends StatefulWidget { 2 @override 3 _QuestionDetailListState createState() => _QuestionDetailListState(); 4} 5 6class _QuestionDetailListState extends State<QuestionDetailList> { 7 @override 8 Widget build(BuildContext context) { 9 Provider.of<AppBarState>(context, listen: false).setTitle("Changed Title"); 10 return Container(); 11 } 12}

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

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

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

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

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

guest

回答1

0

ベストアンサー

build処理中にnotifyListenersで状態の変更の通知を行うことはできません。どうしても行いたければ、以下の様に、WidgetsBinding.instance.addPostFrameCallbackを利用して、build完了後に呼び出すことは可能です。(一度のみ変更が行われる様に、initStateで設定しています)

dart

1class _QuestionDetailListState extends State<QuestionDetailList> { 2 3 4 void initState() { 5 super.initState(); 6 7 WidgetsBinding.instance.addPostFrameCallback((_) => 8 Provider.of<AppBarState>(context, listen: false) 9 .setTitle("Changed Title")); 10 } 11 12 13 Widget build(BuildContext context) { 14 return Container(); 15 } 16}

投稿2020/10/27 05:42

f-miyu

総合スコア1625

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

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

toshi_ki

2020/10/27 06:43

`build`処理中は`notifyListners`送れないんですね。だから、`build`処理中には`build`完了後に実行する処理をスケジュールするだけにするといった感じでしょうか。 ともかく、`addPostFrameCallBack`内に処理を書いたら上手くいきました。大変勉強になりました、ありがとうございます。(*- -)(*_ _)ペコリ
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問