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

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

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

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Flutter

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

同期

複数のディレクトリに存在するファイルを更新した場合に、すべてのファイルにも更新が行われる事、又は、同じ記憶領域に同時にアクセスして内容の整合性が失われてしまう事をを防ぐ制御などを同期と呼びます。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

1回答

2312閲覧

Flutter firestore 同期、非同期処理について

rn383

総合スコア2

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Flutter

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

同期

複数のディレクトリに存在するファイルを更新した場合に、すべてのファイルにも更新が行われる事、又は、同じ記憶領域に同時にアクセスして内容の整合性が失われてしまう事をを防ぐ制御などを同期と呼びます。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

0グッド

0クリップ

投稿2022/06/09 03:00

編集2022/06/09 09:30

Flutterの同期、非同期処理についてご教示いただきたく存じます。

firestoreよりデータを取得し、取得した値をaという変数に格納。
その後、if文にてaの変数の値によって処理を行うプログラムです。
Widgetの中に記載しております。

現状、[1]のget()まで処理が行われ、[2]のelse、最後に[3]のthenの中を処理しています。
本当であれば、[1]→[3]→[2]の順でif文の処理が行われるようにしたいです。
async、awaitを入れれば非同期処理を同期処理にできると思っていたのですが。。。。
何が原因でしょうか?同期、非同期について理解できていないためご教示いただけますと幸いです。

class Home extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ Row(mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ Container( child: Text('メニュー')), ]), Container( child: _buildChild(context), ), ], ), ), ); } Widget _buildChild(BuildContext context) { String uid = FirebaseAuth.instance.currentUser!.uid; String a = ""; Future<void> future1() async { await FirebaseFirestore.instance .collection('users') .doc(uid) .get() //[1] .then((DocumentSnapshot document) async { Map<String, dynamic> data = await document.data()! as Map<String, dynamic>; //[3] a = await data['username'];   //data['username']には"aaa"が入ります }); } future1(); if (a == "aaa") { return Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Container( margin: EdgeInsets.only(top: 100), alignment: Alignment.center, child: Text('はじめまして')), ]); } return Padding( //[2] padding: EdgeInsetsDirectional.fromSTEB(0, 20, 0, 0), child: Row( mainAxisSize: MainAxisSize.max, children: [ Padding( padding: EdgeInsetsDirectional.fromSTEB(15, 0, 0, 0), child: Container( width: 280, height: 100, child: Column( mainAxisSize: MainAxisSize.max, children: [ Container( width: 280, height: 30, child: Padding( padding: EdgeInsetsDirectional.fromSTEB(0, 4, 0, 0), child: Text( 'こんにちは', textAlign: TextAlign.center, ), ), ), ], ), ), ), ], ), ); } }

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

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

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

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

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

rn383

2022/06/09 09:04

class Home extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ Row(mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ Container( child: Text('メニュー')), ]), Container( child: _buildChild(context), ), ], ), ), ); } Widget _buildChild(BuildContext context) { String uid = FirebaseAuth.instance.currentUser!.uid; String a = ""; Future<void> future1() async { await FirebaseFirestore.instance .collection('users') .doc(uid) .get() .then((DocumentSnapshot document) async { Map<String, dynamic> data = await document.data()! as Map<String, dynamic>; a = await data['username']; }); } future1(); if (a == "aaa") { return Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Container( margin: EdgeInsets.only(top: 100), alignment: Alignment.center, child: Text('はじめまして')), ]); } return Padding( padding: EdgeInsetsDirectional.fromSTEB(0, 20, 0, 0), child: Row( mainAxisSize: MainAxisSize.max, children: [ Padding( padding: EdgeInsetsDirectional.fromSTEB(15, 0, 0, 0), child: Container( width: 280, height: 100, child: Column( mainAxisSize: MainAxisSize.max, children: [ Container( width: 280, height: 30, child: Padding( padding: EdgeInsetsDirectional.fromSTEB(0, 4, 0, 0), child: Text( 'こんにちは', textAlign: TextAlign.center, ), ), ), ], ), ), ), ], ), ); } }
ta.fu

2022/06/09 09:16

コードは、元の質問側に追記もしくは修正するようにしてください。 こちら側にコードを入れられても、フォーマットされないので見づらいためです。
rn383

2022/06/09 09:30

失礼しました。 元のコードを修正しました。
guest

回答1

0

ベストアンサー

FlutterでFutureで情報を取り出した結果を利用するにはFutureBuilderを使うのがいいです。

以下はこんな感じかなととりあえず書いた例です。データが確定しない間とかエラーだった場合の処理は適当です。

dart

1class Home extends StatelessWidget { 2 Future<String> future1() async { 3 String uid = FirebaseAuth.instance.currentUser!.uid; 4 String a = ""; 5 await FirebaseFirestore.instance 6 .collection('users') 7 .doc(uid) 8 .get() 9 .then((DocumentSnapshot document) async { 10 Map<String, dynamic> data = 11 await document.data()! as Map<String, dynamic>; 12 a = await data['username']; 13 }); 14 return a; 15 } 16 17 18 Widget build(BuildContext context) { 19 return Scaffold( 20 body: Center( 21 child: Column( 22 mainAxisAlignment: MainAxisAlignment.start, 23 children: <Widget>[ 24 Row(mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ 25 Container(child: Text('メニュー')), 26 ]), 27 Container( 28 child: FutureBuilder( 29 builder: _buildChild, 30 future: future1(), 31 ), 32 ), 33 ], 34 ), 35 ), 36 ); 37 } 38 39 Widget _buildChild(BuildContext context, AsyncSnapshot<Object?> snapshot) { 40 if (snapshot.hasData) { 41 if (snapshot.data == "aaa") { 42 return Column( 43 mainAxisAlignment: MainAxisAlignment.center, 44 children: <Widget>[ 45 Container( 46 margin: EdgeInsets.only(top: 100), 47 alignment: Alignment.center, 48 child: Text('はじめまして')), 49 ]); 50 } 51 return Padding( 52 padding: EdgeInsetsDirectional.fromSTEB(0, 20, 0, 0), 53 child: Row( 54 mainAxisSize: MainAxisSize.max, 55 children: [ 56 Padding( 57 padding: EdgeInsetsDirectional.fromSTEB(15, 0, 0, 0), 58 child: Container( 59 width: 280, 60 height: 100, 61 child: Column( 62 mainAxisSize: MainAxisSize.max, 63 children: [ 64 Container( 65 width: 280, 66 height: 30, 67 child: Padding( 68 padding: EdgeInsetsDirectional.fromSTEB(0, 4, 0, 0), 69 child: Text( 70 'こんにちは', 71 textAlign: TextAlign.center, 72 ), 73 ), 74 ), 75 ], 76 ), 77 ), 78 ), 79 ], 80 ), 81 ); 82 } else { 83 // データが確定しない場合に表示するウィジェットの作成処理 84 return Text("hoge"); 85 } 86 } 87}

ーーーー
await future1();とするのが一番早いです。

ただ、たぶんfuture1();を呼び出す側がasyncがついてない関数なのでしょうか。
だから関数にラッピングしてるのかもしれないですが。

そうすると次善の策としては、thenの中の呼び出し関数の中に[2]の処理を入れるという形になるのかな。
こちらも処理は非同期で実行されるので、変数aの内容をfuture1();の後で使う(同期させる)という使い方はできないですが。

dart

1.then((DocumentSnapshot document) async { 2 Map<String, dynamic> data = await document.data()! as Map<String, dynamic>; //[3] 3 a = await data['username'];   //data['username']には"aaa"が入ります 4 if (a == "aaa") { 5  }else{ 6 //[2] 7 } 8 });

投稿2022/06/09 08:22

編集2022/06/09 09:42
ta.fu

総合スコア1667

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

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

rn383

2022/06/09 09:09

回答ありがとうございます。 全体のコードを乗せたのですが、await future1();とすると、 以下のようにする必要があると思います。 Widget _buildChild(BuildContext context) { ↓ Future<Widget> _buildChild(BuildContext context) async { そうすると、child: _buildChild(context)の箇所で、Future<Widget>を呼び出せないとエラーが出てしまいます。 エラーを取る方法はありますでしょうか? また、widgetの中だからか、if文をthenに入れることはできなそうです。。。
rn383

2022/06/09 10:12

うまく処理できました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問