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

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

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

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

Dart

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

Q&A

1回答

1100閲覧

【Flutter】providerのnotifyListeners()でshowModalBottomSheetを再描画させたいのですができません。

bbiiq

総合スコア51

Flutter

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

Dart

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

0グッド

1クリップ

投稿2023/01/04 09:25

編集2023/01/04 09:32

前提

Flutterの勉強で、メモ帳アプリを作成しています。
そこでshowModalBottomSheetWidgetをproviderのnotifyListeners()で再描画させたいのですができません。
何が足りないのでしょうか?
よければアドバイスいただけるとありがたいです。
よろしくお願いします。

実現したいこと

Buttonを押すとshowModalBottomSheetが表示され、そこに新規メモ帳作成Buttonと今までに作成した下書きのメモ帳が動的に表示させる、といった機能を実装しようといています。
しかし、新規メモ帳作成Buttonを押し、メモ帳作成画面へ移動したあとにメモ内容を保存し、「 Navigator.pop(context);」により戻るとnotifyListeners()が実行されても画面が再描画されません。

発生している問題・エラーメッセージ

なし

該当のソースコード

Dart

1import 'package:flutter/material.dart'; 2import 'package:provider/provider.dart'; 3 4class SendDiary extends StatefulWidget { 5 String? destination; 6 SendDiary(this.destination); 7 8 9 State<SendDiary> createState() => _SendDiary(); 10} 11 12class _SendDiary extends State<SendDiary> { 13 14 Widget build(BuildContext context) { 15 final double deviceHeight = MediaQuery.of(context).size.height; 16 final double deviceWdth = MediaQuery.of(context).size.width; 17 return Scaffold( 18 body: TextButton( 19 onPressed: () { 20 showModalBottomSheet( 21 isScrollControlled: true, 22 context: context, 23 enableDrag: true, 24 builder: (context) { 25 return Consumer<ReShowModalBottomSheet>( 26 builder: (context, model, child) { 27 return Container( 28 height: deviceHeight * 0.4, 29 width: deviceWdth, 30 child: Column(children: [ 31 TextButton( 32//ここでメモ帳作成画面へ遷移 33 onPressed: () async { 34 await Navigator.push( 35 context, 36 MaterialPageRoute( 37 builder: (context) => WriteDiary(null))); 38//メモ帳作成後、戻ってきたタイミングで再描画 39 model.reShowModalBottomSheet(); 40 }, 41 child: Text('新規メモ帳作成画面へ遷移'), 42 ), 43 SingleChildScrollView( 44 physics: BouncingScrollPhysics(), 45 child: Column(children: [ 46 for (int index = 0; 47 index < diaryStorage[0].length; 48 index++) ...{ 49 // new Consumer<ReShowModalBottomSheet>( 50 // builder: (context, model, child) { 51 new TextButton( 52 onPressed: () async { 53//ここで保存していたメモ帳(下書き)をメモ帳作成画面へ展開 54 await Navigator.push( 55 context, 56 MaterialPageRoute( 57 builder: (context) => SendWriteDiary( 58 null, 59 null, 60 null, 61 'null', 62 null, 63 ))); 64//メモ帳作成画面から戻り、画面再描画 65 model.reShowModalBottomSheet(); 66 }, 67 child: Text('下書きの数だけButtonを作成'), 68 ) 69 } 70 ])) 71 ])); 72 }); 73 }); 74 }, 75 child: Text('ShowModalBottomSheet'), 76 )); 77 } 78}

Dart

1import 'package:flutter/material.dart'; 2 3class ReShowModalBottomSheet extends ChangeNotifier { 4 void reShowModalBottomSheet() { 5 notifyListeners(); 6 } 7}

補足情報(FW/ツールのバージョンなど)

[✓] Flutter (Channel stable, 3.3.8, on macOS 13.0.1 22A400 darwin-arm, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 14.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.3)
[✓] VS Code (version 1.73.0)

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

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

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

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

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

guest

回答1

0

以下のサンプルコードで、Consumerのbuilderで作られたウィジェットを再構築していることを確認しました。

提示されたコードと違うのは、State内のbuilderでReShowModalBottomSheetの情報を取り出し、Consumer<ReShowModalBottomSheet>ListenableProvider.valueでラップして、valueに取り出したReShowModalBottomSheetを渡しているところかな。

提示されたコードは実行できないのでそれに近いコードを作ったのだけど、当初動きませんでした。
showModalBottomSheetを作ったところでproviderのエラーが出ました。
それを調べると、Providerのデータ伝播はウィジェットツリー内にとどまるのだけど、showModalBottomSheetは別ツリーになるのでアクセスできない可能性があるとのことです。

なぜ更新されていないかという理由は不明ですが、このような実装で更新を行うことが出来ました。

dart

1import 'package:flutter/material.dart'; 2import 'package:provider/provider.dart'; 3 4class ProvDialog1 extends StatelessWidget { 5 const ProvDialog1({Key? key}) : super(key: key); 6 7 8 Widget build(BuildContext context) { 9 return ChangeNotifierProvider( 10 create: (_) => ReShowModalBottomSheet(), 11 child: const _Scaf(), 12 ); 13 } 14} 15 16class ReShowModalBottomSheet extends ChangeNotifier { 17 void reShowModalBottomSheet() { 18 notifyListeners(); 19 } 20} 21 22class _Scaf extends StatefulWidget { 23 const _Scaf({Key? key}) : super(key: key); 24 25 26 State<_Scaf> createState() => _ScafState(); 27} 28 29class _ScafState extends State<_Scaf> { 30 int count = 0; 31 32 Widget build(BuildContext context) { 33 final data = context.read<ReShowModalBottomSheet>(); 34 return Scaffold( 35 appBar: AppBar( 36 title: const Text("ProvDialog1"), 37 ), 38 body: TextButton( 39 onPressed: () => showModalBottomSheet( 40 isScrollControlled: true, 41 context: context, 42 enableDrag: true, 43 builder: (BuildContext context) { 44 return ListenableProvider.value( 45 value: data, 46 child: Consumer<ReShowModalBottomSheet>( 47 builder: (context, model, child) { 48 return Column(children: [ 49 TextButton( 50 onPressed: () async { 51 count++; 52 model.reShowModalBottomSheet(); 53 }, 54 child: Text("count = $count"), 55 ), 56 ]); 57 }), 58 ); 59 }), 60 child: const Text('Show Dialog'), 61 ), 62 ); 63 } 64}
  • 追記
    ウィジェットの更新指示だけならConsumerを使うよりStatefulBuilderを使った方が楽なのでは?

投稿2023/01/06 02:34

ta.fu

総合スコア1667

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

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

bbiiq

2023/01/09 08:04 編集

回答ありがとございます! とりあえず、Consumer<ReShowModalBottomSheet>をListenableProvider.valueでラップして、valueに取り出したReShowModalBottomSheetを渡してみたのですが、相変わらずって感じだったのでメインとなるクラスとShowModalBottomSheetとShowModalBottomSheetの中のボタンを全て同じツリーの中に入るようやってみます。ありがとうございました。 ウィジェットの更新指示だけならConsumerを使うよりStatefulBuilderを使った方が楽なのでは? →それもやってみたんですけど上手くいかなかったので、勉強も兼ねてProviderを使ってみたっていう感じです!
ta.fu

2023/01/09 11:47

基本的にこういうのは再現するソースが提示されないと、有効な他者の意見を聞くことはできません。 後あるとしたら、勘違い系。 再構築は行ってるけど、データの変更はないので同じ情報が表示されていて、再構築していないと思い込んでいる場合。 builderのreturnでウィジェットを返す前にデバッグ文などを入れて、builderが実行されているかを確認するとか。
bbiiq

2023/01/09 12:42

「基本的にこういうのは再現するソースが提示されないと、有効な他者の意見を聞くことはできません。」 なるほど。main.dartから提示するってことですね。ありがとうございます。 確認してみます。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問