はじめに
Flutterを使ってネイティブアプリを作っているが、Widgetの使い方やFirestoreとのデータ連携の仕方など、コードの書き方が分からずそれなりに苦労している。
一旦分かってしまえばかなり高速でアプリ開発ができそうなので、使い方やコードの書き方のメモを残しておく。
今回はタイトルにある通り、Firestoreを操作する際のarray型のデータ更新についてメモを残す。
Flutterの実行環境
- Ubuntu 18.04LTS(GCP上)
- Flutter 1.22.6
- Dart 2.10.5
- Android Studio 4.1.2
- VScode 1.53.0
メモ内容
Firestoreでarray型のフィールドを作成しておき、それらに対してFieldValue.arrayUnion & arrayRemove
を使い要素の追加、削除を試してみた。
単純なarray型と、arrayの中がさらにMAP型になっている2つのパターンで、コードの書き方を確認してみる。
Firestoreの中のデータ構造は以下の様な感じで準備
以下のmain.dart
を作成してflutter run
を実行
// 必要パッケージのインポート
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
void main() {
runApp(testApp());
}
// メインで呼び出されるクラス。
class testApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final db_ope = CloudFirestore_update();
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text("ホーム"),
), // appBar プロパティに AppBar Widget を追加
body: Center(child: Text("Firestoreの連携テスト")),
// 右下にアクションボタンを設置して、ここをクリックすると、今回試したい機能を実行できる仕組み。
floatingActionButton: Container(
margin: EdgeInsets.only(bottom: 10.0), // ボタンの配置
width: 40.0,
height: 40.0,
child: FloatingActionButton(
//tooltip: 'Increment',
child: Icon(Icons.add),
onPressed: () =>
// 以下の4つの内、どれかのコメントアウトを外して実行結果を確認してみる。
db_ope.add_element_simple('test_document'),
// db_ope.delete_element_simple('test_document'),
// db_ope.add_element_map('test_document'),
// db_ope.delete_element_map('test_document'),
),
),
),
);
}
}
// 今回FirestoreのUpdate操作を行うためのクラスを作成。
class CloudFirestore_update {
static const String target_collection = 'test_collection';
// arrayUnionを使った更新(要素追加)
void add_element_simple(String document_id) {
String colc = target_collection;
Firestore.instance.collection(colc).document(document_id).updateData({
'array_field1':
FieldValue.arrayUnion(['add-data1-1', 'add-data1-2', 'add-data1-2'])
});
}
// ⇒ 2番目と3番目は要素の中身が同じため追加されるデータは2つのみ!
// arrayRemoveを使った更新(要素削除)
void delete_element_simple(String document_id) {
String colc = target_collection;
Firestore.instance.collection(colc).document(document_id).updateData({
'array_field1': FieldValue.arrayRemove(['data1-1', 'add-data1-2'])
});
}
// ⇒ 試しに中身が同じ要素のデータ2つ用意すると、両方とも消えてしまう!
// arrayUnionを使った更新(要素追加) ※arrayの中がMAP型
void add_element_map(String document_id) {
String colc = target_collection;
Firestore.instance.collection(colc).document(document_id).updateData({
'array_field2': FieldValue.arrayUnion([
{
'map2c': 'new_field',
'map2d': 'new_field',
},
]),
});
}
// ⇒ array型の中でそもそも作成していたField構造とは関係なく要素追加が可能なため、注意が必要!
// arrayRemoveを使った更新(要素削除)※arrayの中がMAP型
void delete_element_map(String document_id) {
String colc = target_collection;
Firestore.instance.collection(colc).document(document_id).updateData({
'array_field2': FieldValue.arrayRemove([
{
'map2a': 'data2-a',
'map2b': 'data2b',
},
]),
});
}
// ⇒ array型の中身のMAP内の要素が完全一致していない削除されない。(逆に完全一致するものが複数ある場合は同時に消える。)
}
※Firestoreパッケージが上手く使えない場合は、こちらの記事を参考に!
【FlutterからCloud Firestoreのデータ取得 & データ書き込み】
上記のmain.dart
を実行すると、エミュレータ上では以下の様になる。
右下のアクションボタンをクリックすると、Firestoreの操作が動く。
※アクションボタンで呼び出されるメソッドは、main.dart
内のonPressed:
の部分で設定する。
備考
FieldValue.arrayRemove'
を使った際、indexを利用した削除ができるかと思っていたのだが、色々試したり調べてみたがやり方が分からなかった。(そもそもできない?)
もしやり方が分かれば更新します。