2021/11/02

【Unスクラップ】flutterとfirebaseを用いてアプリを開発してみる3

@ 古曳 純基

FirebaseFlutter

flutterとfirebaseに慣れるために以下の記事を参考にしてアプリの開発を行いました。
https://rightcode.co.jp/blog/information-technology/flutter-firebase-bulletin-board-app-make

firestoreにデータを送信

参考にしていた記事の実装がラストとなります。
PostPageウィジェットのメソッド定義領域に以下のメソッドを追加してみます。
この関数は、TextFieldウィジェットにonSubmitイベントに仕込みます。
このウィジェットのonSubmitイベントは、文字列を入力してEnterを押すと発火するようです(デフォルトの挙動)。

①_onSubmit関数の定義

// サブミットイベント時に発火する関数を解説
// 引数のcontentはTextFieldのデフォルトの挙動で渡ってくるっぽいな
_onSubmitted(String content){
// コレクションリファレンスを作成
    CollectionReference posts = FirebaseFirestore.instance.collection('posts');
// リファレンスに対して、addを行う(ID自動採番)
// ドキュメントの"content"フィールドに引数で受け取ったcontentを入力する
    posts.add({
      "content": content
    });
    
    // 非同期処理を待たずにテキストフィールドをクリアする
    _textEditingController.clear();
}


②TextFieldウィジェットにonSubmitイベントに先程定義した関数を渡す

child: TextField(
       controller: _textEditingController,
       onSubmitted: _onSubmitted, // この一文を追加します
       enabled: true,


ビルドを走らせてみましょう。
以下のように文字列を入力してみます。

入力が完了したらEnterを押します。

※注意点
なぜかわかりませんが、firebase側への書き込みオペレーションを起動すると、flutterのビルドが一時停止されます。
なので、データが反映されているのか確認する際は、一度ビルドし直す必要があります。

ビルドを再度走らせると、トップページは以下のように表示されています。
データの書き込みがうまくいっていますね。(この画像を撮る前に、何回か書き込みを行なっていました...)


書いたコードは以下の通りです。

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';


// void main() {
//   runApp(const MyApp());
// }


// firebaseを導入した場合のmain関数
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase?.initializeApp();
  runApp(MyApp());
}


class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);


  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      // 右上のdebugタグを外すためのやつ
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.yellow,
      ),
      home: const MyHomePage(title: '掲示板デモアプリ'),
    );
  }
}


class MyHomePage extends StatefulWidget {
  const MyHomePage({required this.title}) : super();


  final String title;


  @override
  State<MyHomePage> createState() => _MyHomePageState();
}


// ここから書き換えてみました
// Stateを継承しているウィジェットが見た目の部分のビルドを行っています
class _MyHomePageState extends State<MyHomePage> {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        actions: [
          IconButton(
            icon: Icon(Icons.edit),
            onPressed: () {
              Navigator.of(context).push(MaterialPageRoute(builder: (context) {
                return PostPage();
              }));
            },
          ),
        ],
      ),
      body: StreamBuilder<QuerySnapshot>(
      stream: FirebaseFirestore.instance.collection('posts').snapshots(),
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          // 通信状況が悪いときにプログレスインジケーターの表示
          return Center(child: CircularProgressIndicator());
        }
        // 通信が正常にいっているのであれば
        return ListView(
          children: snapshot.data!.docs.map((DocumentSnapshot document) {
            final documentData = document.data()! as Map;
            print("---------------");
            print(documentData["content"]);
            print("---------------");
            return Card(
              child: ListTile(
                title: Text(document.exists? documentData['content'] : "データが存在していません" ),
                subtitle: const Text("サブタイトル"),
              ),
            );
          }).toList(),
        );
      },
    ),
    );
  }
}


// 投稿ページの実装
class PostPage extends StatefulWidget {


  @override
  _PostPagePageState createState() => _PostPagePageState();
}


class _PostPagePageState extends State<PostPage> {


  // 入力情報をハンドリングするためのコントローラを作成
  TextEditingController _textEditingController = TextEditingController();


  // データ送信用のプラベートメソッドを作成
  _onSubmitted(String content){
    CollectionReference posts = FirebaseFirestore.instance.collection('posts');
    // 自動採番でデータをfirestore側に作成する
    posts.add({
      "content": content
    });
    
    /// 入力欄をクリアにする
    _textEditingController.clear();
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("投稿画面"),
      ),
      body: Center(
        child: TextField(
          controller: _textEditingController,
          onSubmitted: _onSubmitted, // データ送信
          enabled: true,
          maxLength: 50, // 入力数
          style: TextStyle(color: Colors.black),
          obscureText: false,
          maxLines:1 ,
          decoration: const InputDecoration(
            icon: Icon(Icons.speaker_notes),
            hintText: '投稿内容を記載します',
            labelText: '内容 * ',
          ),
        ),
      ),
    );
  }
}


念のためにfirestoreの方も確認してみましょう。
ドキュメントが追加されていますね。


以上で投稿アプリの作成を終わります。

締めの一言

エラーへの対処大変!

© 2021 powerd by UnReact