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']}");
},
),
),
);
}
}

参考としたサイト
コメント