【Futter】FirebaseのFirestoreからイベントを取得する

Flutter状態管理

FlutterFirestoreを使った情報で私でも理解できる記事が少なかったので自分なりの備忘録になります。今回はFirestoreからイベントを取得し表示する部分についてです。

前提

今回の使用したFlutterとFirebaseのバージョンのバージョンです。(2023.05時点)
こちらはなるべく最新のものを使うのがベターかなと思います。

Flutter 3.7.10 
Tools • Dart 2.19.6 • DevTools 2.20.1
dependencies:
  flutter:
    sdk: flutter
  cloud_firestore: ^4.5.1

Firestoreの情報

今回はFirebaseの登録などは記載しないため他の記事を参考ください。
こちらなど参考になると思います。

 01.Firebaseの概要|Flutter実践入門

今回、下記のような形であらかじめデータを保管してあります。

今回の2つのポイント

今回のFirestoreのイベント取得におけるポイントは以下の2点かなと思います。
それぞれ解説していきます。

  • 取得するための関数(getEvent())
  • 表示するためのFutureBuilder

取得するための関数(getEvent())

全体

全体コードとしては以下のように実装しました。

//Firebaseのイベント取得
  static final firebaseEvents = FirebaseFirestore.instance.collection('calendar_events');
  static Future<void> getEvent(List<String>ids) async {
    var eventList = [];
    try {
      // firebaseの日付データ取得
      await Future.forEach(ids, (String id) async {
        var doc = await firebaseEvents.doc(id).get();

        Event events = Event( 
            event: doc.data()['event'],
            eventDay: doc.data()['date']
        );
        eventList.add(events);
      });
      return eventList;

    } catch(e) {
      print('error: $e');
    }
  }

ポイントとしては以下の3つになります。

①Future.forEach

      await Future.forEach(ids, (String id) async {

非同期でループ処理するためにFuture.forEachを使用します。
引数で取得したidをもとにイベントの数だけリストに追加していきます。

非同期のループ処理について:

【Flutter】ループで非同期処理を行う

②Eventクラス

import 'package:cloud_firestore/cloud_firestore.dart';
//イベントクラス
class Event {
  final String event;
  Timestamp eventDay;

  Event({this.event, this.eventDay});
}

こちらは実践ぽくクラスを別ファイルで定義しています。
idとかイベントの時間とかを保存する際にこちらに追加することで柔軟に対応が可能になります。

クラスの使い方:

【Flutter/Dart】クラスとは?概念や使い方を徹底解説!|TERUPRO
こんにちは、テルプロです! 「クラス(Class)の使い方がわからない」とお悩みではないでしょうか? テルプロ 本記事で

③FireStoreの実装のやり方

Firestoreのインスタンスを宣言します。
.collection(‘コレクション名’)とすることで自分でFirebaseのコレクションを呼べるようになります。

static final firebaseEvents = FirebaseFirestore.instance.collection('calendar_events');

非同期で取得するために awaitをつけます。
また、doc().getでFireStoreの情報を取得できます。

今回は引数をidとし、最後にFirestoreを呼び出す際にFirestoreのドキュメントIDを引数に設定することで自分が取得したいドキュメントIDの中の情報を呼び出せるようにしています。

var doc = await firebaseEvents.doc(id).get();

イベントクラスのeventとeventDayに追加します。
上記のdocを元にdoc.data()[‘フィールド名’]とすることで各フィールド情報を追加できます。
この辺りの呼び出し方や名前なんかはFirebaseに慣れていくしかないかなと…

Event events = Event( 
    event: doc.data()['event'],
    eventDay: doc.data()['date']
);

表示するためのFutureBuilder

関数ができたため後は実際に画面で呼んであげます。
全体の処理としては以下のようにしました。

全体コード

class TestPage extends StatelessWidget {
   TestPage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final List<String> id = ['CBJ1nH4CVXn16oYoGvND'];
    return Scaffold(
      body: FutureBuilder(
        future: FireStore.getEvent(id),
        builder: (BuildContext context, snapshot){
          return Center(
            child: ElevatedButton(onPressed: (){
                  final doc = snapshot.data[0];
                  print('${doc.event}');
                },
                    child: Text('Button')
                ),
          );
        },
      )
    );
  }
}

ポイントとしては2つです。

①FutureBuilder

こちらも非同期で呼ぶためにFutureBuilderを使用します。
詳細はこちらが分かりやすかったのでぜひ。

【Flutter Widget of the Week #6】FutureBuilderを使ってみた

future: として先ほど記載したFireStore.getEvent()を使用します。
引数のidを今回は手打ちでドキュメントIDを宣言しています。
この辺を別で取得しリスト化するとより実用的なアプリに近づくかなと思います。

    final List<String> id = ['CBJ1nH4CVXn16oYoGvND'];
      body: FutureBuilder(
          future: FireStore.getEvent(id),
          builder: (BuildContext context, snapshot){

②実際に呼んでみる

最後に呼び足しています。
今回はボタンを押してprintするといったシンプルなものです。

こちらも慣れですが、呼び出す際は、snapshot.data[‘呼びたいインデックス’]とします。
こちらも0と初期値にしてますが、indexなどとして他の実装を加えると動的なアプリになります。
Doc.eventとすることで1番目のイベントを表示することができます。

ElevatedButton(onPressed: (){
  final doc = snapshot.data[0];
  print('${doc.event}');
},

まとめ

自分なりにポイントを上げてきました。
Firestoreの値を呼ぶために必要なのは、以下のポイントだと自分なりに解釈しました。

  • 取得するための関数(getEvent())
    ①Future.forEach
    ②Eventクラス
    ③FireStoreの実装のやり方
  • 表示するためのFutureBuilder
    ①FutureBuilder
    ②実際に呼んでみる

こちら以外にもさまざまな方法があると思います。
Firestoreの追加の仕方など含め別記事でまた解説できればと思います。

ではまた。

コメント

タイトルとURLをコピーしました