[Flutter×Firebase] Cloud Firestoreでのデータ読み込み

flutter

Cloud FirestoreのCRUDを調べたのですがReadの方法がよくわからなかったのでまとめました。

ソースコード

ソースコードはgithubに公開しています。

firebaseでプロジェクトを作成し「google-services.json」をandroid/app/src配下に格納すると動作します。

解説

cloud firestoreからデータを読み込む方法として以下の方法があります。

・Streamによる読み取り
・非同期処理(future)による読み取り

また読み取る対象としては以下があります。
・collection
・document

それぞれの方法をまとめたため紹介します。

データベースには以下データが入っています。

bbbとcccのドキュメントのフィールドは以下が格納されています。
name:bbb age:25
name:ccc age:30

stream×collectionによる読み取り

streamを利用するとデータベースの変更があった場合、表示データが更新されます。
例えばname:xxx age:35という内容をデータベースに追加した場合、アプリケーションの表示データが即時に更新されます。
以下コードでやっていることは「users」というcollectionを取得し、collectionの中には複数のdocument(aaa,bbb,ccc)があるため、そのデータをlistviewで表示しています。

import 'package:flutter/material.dart';

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'firebase_test',
      home: GetCollectionUseStream(),
      //home: GetDocUseStream(),
      //home: GetCollectionUseFuture(),
      //home: GetDocUseFuture(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final Stream<QuerySnapshot> _users = FirebaseFirestore.instance.collection('users').snapshots();

    return Scaffold(
      body: Center(
        child: StreamBuilder<QuerySnapshot>(
          stream: _users,
          builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
            if (snapshot.hasError) {
              return const Text('Something went wrong');
            }

            if (snapshot.connectionState == ConnectionState.waiting) {
              return const Text("Loading");
            }

            return ListView(
              children: snapshot.data!.docs.map((DocumentSnapshot document) {
                Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
                return ListTile(
                  title: Text('name:${data['name']}'),
                  subtitle: Text('age:${data['age'].toString()}'),
                );
              }).toList(),
            );
          },
        ),
      ),
    );
  }
}

stream×documentによる読み取り

stream×collectionは複数のdocumentを取得しましたが、単一のdocumentを取得する方法になります。今回はaaaというdocumentを1つ取得し表示させています。

import 'package:flutter/material.dart';

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'firebase_test',
      //home: GetCollectionUseStream(),
      home: GetDocUseStream(),
      //home: GetCollectionUseFuture(),
      //home: GetDocUseFuture(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    CollectionReference _users = FirebaseFirestore.instance.collection('users');

    return Scaffold(
      body: Center(
        child: StreamBuilder<DocumentSnapshot>(
          stream: _users.doc('aaa').snapshots(),
          builder:
              (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {

            if (snapshot.hasError) {
              return const Text("Something went wrong");
            }

            if (snapshot.connectionState == ConnectionState.waiting) {
              return const Text("Loading");
            }

            Map<String, dynamic> data = snapshot.data!.data() as Map<String, dynamic>;
            return Text("name:${data['name']}   age:${data['age']}");
          },
        ),
      ),
    );
  }
}

future×collectionによる読み取り

futureの場合はデータベースが更新されてもアプリケーションのデータが更新されることはありません。streamとfutureは作成するアプリケーションの要件により使い分けることとなります。

import 'package:flutter/material.dart';

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'firebase_test',
      //home: GetCollectionUseStream(),
      //home: GetDocUseStream(),
      home: GetCollectionUseFuture(),
      //home: GetDocUseFuture(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final Future<QuerySnapshot> _users = FirebaseFirestore.instance.collection('users').get();

    return Scaffold(
      body: Center(
        child: FutureBuilder<QuerySnapshot>(
          future: _users,
          builder:
              (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
                if (snapshot.hasError) {
                  return const Text('Something went wrong');
                }

                if (snapshot.connectionState == ConnectionState.waiting) {
                  return const Text("Loading");
                }

                return ListView(
                  children: snapshot.data!.docs.map((DocumentSnapshot document) {
                    Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
                    return ListTile(
                      title: Text('name:${data['name']}'),
                      subtitle: Text('age:${data['age'].toString()}'),
                    );
                  }).toList(),
                );
          },
        ),
      ),
    );
  }
}

表示はstream×collectionによる読み取りと同じです。

future×documentによる読み取り

今回はbbbのデータを取得し、表示しています。

import 'package:flutter/material.dart';

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'firebase_test',
      //home: GetCollectionUseStream(),
      //home: GetDocUseStream(),
      //home: GetCollectionUseFuture(),
      home: GetDocUseFuture(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    CollectionReference _users = FirebaseFirestore.instance.collection('users');

    return Scaffold(
      body: Center(
        child: FutureBuilder<DocumentSnapshot>(
          future: _users.doc('bbb').get(),
          builder:
              (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {

            if (snapshot.hasError) {
              return const Text("Something went wrong");
            }

            if (snapshot.connectionState == ConnectionState.waiting) {
              return const Text("Loading");
            }

            Map<String, dynamic> data = snapshot.data!.data() as Map<String, dynamic>;
            return Text("name:${data['name']}   age:${data['age']}");
          },
        ),
      ),
    );
  }
}

参考としたサイト

コメント

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