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

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

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

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

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Dart

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

Q&A

解決済

1回答

6055閲覧

[Flutter]リビルドされているが画像が更新されない

fathy

総合スコア254

Flutter

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

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Dart

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

0グッド

1クリップ

投稿2020/05/11 16:36

編集2020/05/13 12:41

##やりたいこと
Providerを使って,データが変更されたらリビルドして表示画像を変更したいです。

##困っていること
リビルドはされているのですが表示が変わりません。

初期状態は全て①の箇所の画像はAssetの画像が表示されています。
それを編集してImage.memoryの別の画像
コンソールでログを見るとの箇所で確かに②の箇所で

_[log] Image(image: MemoryImage(Uint8ArrayView#25b1e, scale: 1.0), frameBuilder: null, loadingBuilder: null, alignment: center, this.excludeFromSemantics: false, filterQuality: low)

の表示があります。

なぜかAndroidの画面での表示が変わりません。

Flutter Inspectorでは全て
image: AssetImage(bundle: null, name: "images/boxImage.jpg")
と表示されています。

##調べたこと
Flutter Image Widget won't update on change state

このような記事を見つけたのですが,Image.fileの話で関係ないのかなと思いました。
##開発環境
Android Studio 3.6.3
Flutter 1.14.6
Dart 2.8.0

現在Flutterで開発をはじめて2週間ほどです。
よろしくお願いいたします。

##追記
見にくいかと思いますがファイル全体です。
// function スコアボックス
List<Widget> _scoreCellList(BuildContext context, int inning) {
の箇所が該当箇所です。
文字数制限のため元々の質問をコードを削除しました。
よろしくお願いいたします。

Dart

1 2 3class ScorebookPage extends StatelessWidget { 4 ScorebookPage({this.battingTurn}); 5 6 static const _cellHeight = 50.0; 7 static const _cellWidth = 70.0; 8 9 BattingTurn battingTurn; 10 11 bool get _isBattingTurnFirst => battingTurn == BattingTurn.first; 12 13 14 Widget build(BuildContext context) { 15 //画面サイズ取得 16 final size = MediaQuery.of(context).size; 17 18 ImageCache().clear(); 19 return Scaffold( 20 //https://stackoverflow.com/questions/51972371/bottom-overflow-by-30px 21 //これないとbottom overflow する 22 resizeToAvoidBottomPadding: false, 23 24 body: SafeArea( 25 child: Container( 26 width: size.width, 27 height: size.height, 28 child: Column( 29 verticalDirection: VerticalDirection.down, 30 children: <Widget>[ 31 Expanded( 32 child: BidirectionalScrollViewPlugin( 33 child: _buildWidgets(context))) 34 ], 35 ), 36 ), 37 ), 38 floatingActionButton: Column( 39 verticalDirection: VerticalDirection.up, 40 mainAxisSize: MainAxisSize.min, 41 children: <Widget>[ 42 FloatingActionButton( 43 heroTag: 'flip', 44 onPressed: () { 45 if (_isBattingTurnFirst) { 46 Navigator.of(context).pushNamed('/scorebookSecond'); 47 } else { 48 Navigator.of(context).pop(); 49 } 50 }, 51 tooltip: _isBattingTurnFirst ? '後攻のシートへ' : '先攻のシートへ', 52 child: Icon(Icons.flip_to_back), 53 ), 54 Container( 55 // 余白のためContainerでラップ 56 margin: const EdgeInsets.only(bottom: 16), 57 child: FloatingActionButton( 58 heroTag: 'menu', 59 backgroundColor: originalGreen, 60 onPressed: () { 61 print('pressed'); 62 }, 63 child: Icon( 64 Icons.menu, 65 size: 32, 66 ), 67 ), 68 ), 69 ], 70 ) // This trailing comma makes auto-formatting nicer for build methods. 71 ); 72 } 73 74 Widget _buildWidgets(BuildContext context) { 75 return Container( 76 padding: const EdgeInsets.all(8), 77 height: _cellHeight * 13, 78 color: Colors.white, 79 child: Row( 80 children: [ 81 Column( 82 children: _scoreCellList(context, 1).map((widget) { 83 return widget; 84 }).toList(), 85 mainAxisSize: MainAxisSize.min, 86 ), 87 Column( 88 children: _scoreCellList(context, 2).map((widget) { 89 return widget; 90 }).toList(), 91 mainAxisSize: MainAxisSize.min, 92 ), 93 Column( 94 children: _scoreCellList(context, 3).map((widget) { 95 return widget; 96 }).toList(), 97 mainAxisSize: MainAxisSize.min, 98 ), 99 Column( 100 children: _scoreCellList(context, 4).map((widget) { 101 return widget; 102 }).toList(), 103 ), 104 Column( 105 children: _scoreCellList(context, 5).map((widget) { 106 return widget; 107 }).toList(), 108 ), 109 Column( 110 children: _scoreCellList(context, 6).map((widget) { 111 return widget; 112 }).toList(), 113 ), 114 Column( 115 children: _scoreCellList(context, 7).map((widget) { 116 return widget; 117 }).toList(), 118 ), 119 Column( 120 children: _scoreCellList(context, 8).map((widget) { 121 return widget; 122 }).toList(), 123 ), 124 Column( 125 children: _scoreCellList(context, 9).map((widget) { 126 return widget; 127 }).toList(), 128 ), 129 Column( 130 children: _scoreCellList(context, 10).map((widget) { 131 return widget; 132 }).toList(), 133 ), 134 Column( 135 children: _scoreCellList(context, 11).map((widget) { 136 return widget; 137 }).toList(), 138 ), 139 Column( 140 children: _scoreCellList(context, 12).map((widget) { 141 return widget; 142 }).toList(), 143 ), 144 Column( 145 children: _scoreCellList(context, 13).map((widget) { 146 return widget; 147 }).toList(), 148 ), 149 ], 150 crossAxisAlignment: CrossAxisAlignment.stretch, 151 ), 152 ); 153 } 154 155 // function スコアボックス 156 List<Widget> _scoreCellList(BuildContext context, int inning) { 157 List<Widget> list = new List(); 158 159 ImageCache().clear(); 160 // イニング行 161 list.add(Container( 162 height: _cellHeight / 2, 163 width: _cellWidth, 164 child: Center( 165 child: Text(inning.toString()), 166 ), 167 decoration: BoxDecoration( 168 border: Border( 169 top: const BorderSide(color: originalGreen, width: 0.5), 170 right: BorderSide( 171 color: originalGreen, width: inning == 13 ? 0.5 : 0), 172 left: const BorderSide(color: originalGreen, width: 0.5))), 173 )); 174 175 final scoreBoxDatasModel = _isBattingTurnFirst 176 ? Provider.of<FirstScoreBoxDatasModel>(context) 177 : Provider.of<SecondScoreBoxDatasModel>(context); 178 log('rebuild score cell'); 179 // スコア行 10行 180 for (var order = 1; order <= 10; order++) { 181 // TODO(kazuki): ProviderのSelectorでリビルドを減らす 182 // 監視するところを全部にしないで切り分ける? 183 // イニングごととかでリビルドが走るようにとか 184 185 final scoreBoxData = scoreBoxDatasModel.scoreBoxData(inning, order); 186 187 if (scoreBoxData.changed != null) { 188// log(scoreBoxData.changed); 189// log(scoreBoxData.inning.toString()); 190// log(scoreBoxData.order.toString()); 191// log(scoreBoxData.imageBytes.toString()); 192 } 193// log(_isBattingTurnFirst.toString()); 194 final image = scoreBoxData.imageBytes != null 195 ? Image.memory( 196 scoreBoxData.imageBytes, 197 key: Key(scoreBoxData.id), 198 ) 199 : Image.asset( 200 'images/boxImage.jpg', 201 key: Key(scoreBoxData.id), 202 ); 203// final image = Image.memory(scoreBoxData.imageBytes, key: UniqueKey(),) 204// log(image.toString()); 205 list.add( 206 Hero( 207 tag: scoreBoxData.id, 208 child: GestureDetector( 209 child: Container( 210 padding: const EdgeInsets.all(0), 211 color: Colors.white, 212 height: _cellHeight, 213 width: _cellWidth, 214 child: Container( 215 child: Center( 216 child: Text(scoreBoxData.changed, 217 style: TextStyle(color: Colors.black87)), 218 ), 219 decoration: BoxDecoration( 220 border: Border( 221 top: const BorderSide(color: originalGreen, width: 0.5), 222 bottom: BorderSide( 223 color: originalGreen, width: order == 10 ? 0.5 : 0), 224 right: BorderSide( 225 color: originalGreen, width: inning == 13 ? 0.5 : 0), 226 left: const BorderSide(color: originalGreen, width: 0.5), 227 ), 228 ), 229 ), 230 ), 231 onTap: () { 232 Navigator.push( 233 context, 234 ScorebookToHandWriteRoute( 235 widget: HandWritePageView( 236 initialPageOrder: scoreBoxData.order, 237 inning: scoreBoxData.inning, 238 scoreBoxDatasModel: scoreBoxDatasModel), 239 ), 240 ); 241 }, 242 ), 243 ), 244 ); 245 } 246 247 list.add(Container( 248 width: _cellWidth, 249 height: _cellHeight / 2, 250 decoration: const BoxDecoration( 251 border: Border( 252 top: BorderSide(color: originalGreen, width: 0.5), 253 bottom: BorderSide(color: originalGreen, width: 0.5), 254 left: BorderSide(color: originalGreen, width: 0.5), 255 )))); 256 257 return list; 258 } 259 260}

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

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

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

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

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

satokei

2020/05/12 03:32

Image.memoryにkeyを追加したらどうなるでしょう?  Image.memory(data.imageBytes, key: UniqueKey())
fathy

2020/05/12 04:03 編集

ご質問ありがとうございます。 試しましたが変化はありませんでした。 keyについて理解できていないのですが, 下記のようにキーを揃えるパターンも変化しませんでした。。。 final image = scoreBoxData.imageBytes != null ? Image.memory( data.imageBytes, key: Key(data.id), ) : Image.asset( 'images/boxImage.jpg', key: Key(data.id), );
satokei

2020/05/12 04:24

Image.fileについてですが、 質問のstackoverflowに記載されているIssueで、 「キャッシュのクリア」と「keyを追加」で回避できるとあります。 imageCache.clear() も実行するとどうでしょう? https://github.com/flutter/flutter/issues/17419
fathy

2020/05/12 11:12

遅くなりすみません。 変わりませんでした。。 キャッシュのクリアとキーの追加を行いましたが,画像は同じままです。
satokei

2020/05/13 04:52

なるほど、分からないですね....???? ちなみに、画像以外を表示させると変化はあるのでしょうか? (もしくは、表示件数が変わっているとか)
fathy

2020/05/13 11:45

すみません!画像以外でも変わりませんでした! 試したコードは child: Center( child: image, ) の箇所を child: Center( child: Text(data.changed), ), に変更しました。 画像が変更されたあともテキストが変わりませんでした。 ログの出力はされているのですが。。。 何が考えられるでしょうか????‍♀️
satokei

2020/05/13 12:26

_boxListメソッドを使用している箇所に問題があるかもしれませんので、 コードを提示してください。
satokei

2020/05/13 13:03 編集

コード提示ありがとうございます。 確認しましたところ、話が戻ってすみませんが、 イメージキャッシュのクリア方法は、  ImageCache().clear(); ではなくて、  imageCache.clear(); ですね。 試してみてみてください。
fathy

2020/05/13 13:06

すみません。。 クラス内の変数_imageChacheとして実行しましたが,画像は同じままでした????‍♀️
satokei

2020/05/13 13:10 編集

imageCacheは、グローバルなgetterですので、 「imageCache.clear();」としてください。
fathy

2020/05/13 13:14

スペスミスでおかしなことになってました。????‍♀️ ようやくキャッシュクリアできたかと思うのですが,結果は同じでした。 キーを設定してもダメでした。。。
satokei

2020/05/13 13:17

> クラス内の変数_imageChacheとして実行しましたが, クラス内の変数として定義していないですよね?それは削除してください。
fathy

2020/05/13 13:18

してないです! アンダーバーもつけてないのでグローバルのものを参照できているはずです!
fathy

2020/05/13 13:19

``` @override Widget build(BuildContext context) { //画面サイズ取得 final size = MediaQuery.of(context).size; imageCache.clear(); return Scaffold( ``` このようにしました。
satokei

2020/05/13 13:19

了解しました!
satokei

2020/05/13 13:28

ちなみに、画像の代わりに「Text(scoreBoxData.changed)」を表示してもらいましたが、 初期表示時とリビルド時で実は内容が同じってことはないですよね。 例えば、「Text(image.toString())」としても変わらないですか?
fathy

2020/05/13 13:38

Text(data.changed)の内容もログの上では変化していました。 Text(image.toString())としてみても Image-[<'4be7c326-3c64-48 などと表示されこの文字列の変化は確認できませんでした。
fathy

2020/05/13 13:41

今,satokei様のアドバイスとは関係ないのですが,リビルドする数が多すぎるのではないかと思い,大幅に減らして実行しましたが結果は同じでした。
satokei

2020/05/13 13:43

ありがとうございます。 ....????
guest

回答1

0

ベストアンサー

原因は、BidirectionalScrollViewPluginStatefulWidgetであり、
リビルドされても再利用されてしまっているからです。

再利用させないためには、
BidirectionalScrollViewPlugin
keyを設定してあげるのが手っ取り早そうですが、
コンストラクタにkeyがないので渡せないですね。

以下のようにコンストラクタにkeyをつけて、
UniqueKeyを渡してあげれば、画像が変わると思います。
またプラグインの作者へプルリクを投げるとよいかと

Dart

1class BidirectionalScrollViewPlugin extends StatefulWidget { 2 BidirectionalScrollViewPlugin({ this.child, 3 Key key, // <==★これを追加 4 this.childWidth, 5 this.childHeight, 6 this.velocityFactor, 7 this.initialOffset, 8 this.scrollDirection, 9 this.scrollListener, 10 this.scrollOverflow = Overflow.visible, 11 }) : super(key: key); // <==★これを追加 12~略~ 13}
  • pub.dev

https://pub.dev/packages/bidirectional_scroll_view

  • GitHub

https://github.com/toufikzitouni/flutter-bidirectional_scrollview_plugin

投稿2020/05/13 14:16

編集2020/05/14 01:10
satokei

総合スコア1217

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

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

fathy

2020/05/13 14:29

本当にありがとうございます????‍♀️ はじめからコード全体を載せるべきでした。 確認に手間どりそうなので少々お時間下さい。
fathy

2020/05/13 14:47

変わりました!!! 本当にたくさんの時間を割いて頂いてありがとうございます! 感動しました。 ????‍♀️????‍♀️????‍♀️
satokei

2020/05/13 14:57

おお!よかったです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問