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

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

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

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

Dart

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

Q&A

解決済

1回答

637閲覧

onPressedが機能しない

totti0147

総合スコア2

Flutter

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

Dart

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

0グッド

0クリップ

投稿2023/11/01 08:35

編集2023/11/01 09:09

Flutterでテキストフィールドに入力された文章をIconButtonを押すとサーバーに送信するコードを書いています。

コード自体にエラーは出ていないのですが自分のスマホで試してみたところ反応がありませんでした。きちんと機能するようにしたいのですがどこがおかしいのかが分かりません。

原因となっている部分の指摘と改善案を教えて頂きたいです。
よろしくお願いします。

試したことが書かれていないと指摘がありましたが、まだ本当に初心者で
このコードもコピペしたものをいじりながらなんとかエラーを全部消した状態なので
申し訳ないのですが修正するのに何をどう試すべきなのかも分かっていません。

回答を参考に勉強させて下さい。よろしくお願いします。

### 該当のソースコード import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:project_d/dropdown.dart'; final textSendingProvider = FutureProvider<void>((ref) async { final text = ref.read(textEditingControllerProvider).text; final serverUrl = 'http://192.168.1.124:3000/posts'; if (text.isNotEmpty) { final response = await http.post( Uri.parse(serverUrl), headers: <String, String>{ 'Content-Type': 'application/json; charset=UTF-8', }, body: jsonEncode({'text': text}), ); if (response.statusCode == 200) { print('Text sent successfully'); } else { print('Failed to send text. Status code: ${response.statusCode}'); throw Exception('Failed to send text.'); } } }); final textEditingControllerProvider = Provider<TextEditingController>((ref) { return TextEditingController(); }); class TextPostScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final textSendingAsyncValue = ref.watch(textSendingProvider); return Column( children: <Widget>[ Stack( children: <Widget>[ Container(margin: EdgeInsets.fromLTRB(32, 16, 0, 0), child: Text('How do you say this in Japanese?', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold ), ), ), ExpansionTile( title: Text(''), children: [ Container( margin: EdgeInsets.fromLTRB(8, 0, 8, 10), height: 140, width: 800, decoration: BoxDecoration( color: Colors.white, border: Border.all( width: 2, color: Colors.black ), ), child: TextField( controller: ref.watch(textEditingControllerProvider), keyboardType: TextInputType.multiline, maxLines: null, decoration: InputDecoration( contentPadding: EdgeInsets.fromLTRB(10, 36, 0, 36), ), ), ), ], ), Positioned( left: 320, right: 20, top: 146, bottom: 10, child: IconButton( icon: Icon(Icons.send, color: Colors.blue), onPressed: () {            //機能させたいところ ref.read(textSendingProvider); } ), ), if (textSendingAsyncValue.when( data: (value) => true, loading: () => false, error: (error, stackTrace) => false, )) Text('Text sent successfully'),     ], ), Row( children: <Widget>[ Expanded( child: Container( margin: EdgeInsets.fromLTRB(10, 0, 100, 0), child: Text('All your requests', ), ), ), CreateDropdown(), ], ), Flexible( child: ListView( children: <Widget>[ Stack( children: <Widget>[ Container( margin: EdgeInsets.fromLTRB(8, 0, 8, 0), height: 140, decoration: BoxDecoration( color: Colors.white, border: Border.all( width: 2, color: Colors.black ), ), child: Align( alignment: Alignment(-0.984, -0.96), child: Icon(Icons.star,color: Colors.grey), ), ), Container( margin: EdgeInsets.fromLTRB(41, 6, 10, 100), child: Text( 'It was just failure after failure. I had to try lots of things before I found a way that worked for me.', style: TextStyle( fontSize: 16, color: Colors.indigo, ), ), ), Container( margin: EdgeInsets.fromLTRB(40, 62, 6, 40), child: Text( 'それはもう挫折の連続でした。自分に合った方法を見つけるまで色々試したよ。', style: TextStyle( fontSize: 16, ), ), ), ], ), ], ), ), ], ); } } ### 補足情報(FW/ツールのバージョンなど)

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

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

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

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

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

guest

回答1

0

ベストアンサー

TextPostScreenのbuildが呼び出された瞬間にtextSendingProviderのFuture処理が実施されます。
これはFutureProvider内のif (text.isNotEmpty) {の前にデバッグ文なんかを入れておけば、画面が出た瞬間にそのメッセージが出てくることで確認できると思います。

そしてonPressed中のあの書き方では、FutureProviderの中身の動作を再動作させるということにはなりません。

今回の実装を流用しつつ私が実装するとしたら、以下の様にするかな。

  • ボタンを押したらhttpのリクエストを送り、それが終了したらスナックバーかダイアログを出すようにする。
    現在の実装は、ボタンを押してFuture完了したらTextを下に表示させようとしているけど。
  1. textSendingProviderはFutureProviderとするのではなく、単純なFuture<void>を返す関数にする。
  2. 上の関数をonPressedで呼び出し、thenもしくはawaitで待ったあとshowSnackBarやダイアログを出すなどして送信完了したのを知らせる。
    この場合、当然ですがbuild直下に入れているFutureProviderのwatchを外す。

もしくは、個人的にはあまり好きではないけど、以下の様にするとか。

  • FutureProviderを起動するためのProviderを用意しIconButtonではそれ経由でFutureProviderを動かす。
  1. final counter = StateProvider<int>((ref) => 0);を用意する。
  2. FutureProviderの中で、counterをwatchしておく。
  3. onPressedではref.read(counter.notifier).state++;とする。

投稿2023/11/02 00:14

ta.fu

総合スコア1740

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

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

totti0147

2023/11/02 06:08

有難うございます!参考にして頑張ってみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問