FlutterのGoogleCloudFirestoreとRealtimeDatabase

Googleは、データの永続性を長期にわたって維持するためのサービスを提供しています。アプリケーションで使用されるデータは、必要なときに利用可能で、簡単にアクセスでき、できればアプリですぐに使用できるように構成されている必要があります。

CloudFirestoreとFirebaseRealtimeDatabaseは、Googleが提供する2つのサービスです。どちらもアプリケーションに必要なことを実行できますが、両者の間にはさまざまな違いがあります。これにより、実際には特定のアプリケーションタイプに最適になります。

この記事では、Flutterアプリケーションのクエリに適したデータベースを紹介します。はじめに、この記事の内容、使用例、前提条件、およびプロセスの概要を簡単に説明します。

カバーする内容

この記事では、以下について説明します。

  • FlutterアプリをCloudFirestoreとRealtimeDatabaseに別々に接続する方法
  • データクエリの観点からどのように差別化されているか

私たちの例

プラットフォームの登録ユーザーが特定のトピックや決定に投票できるアプリケーションを作成します。

使用するサンプルデータセットを使用すると、CloudFirestoreとRealtimeDatabaseの違いを次の2つの理由で紹介できます。

  • Flutterアプリケーションとの接続
  • 処理できるクエリ機能の違い

前提条件

  • 基本的なFlutterアプリケーションの作成方法に関する知識
  • NoSql/ドキュメントベースのデータストレージの概念に精通している
  • Flutterの外部にあるか、Flutterを使用しているかにかかわらず、CloudFirestoreまたはRealtimeDatabaseのいずれかを知っていることはプラスです

駆け抜ける

私たちのフローは次の構造を取ります:

  • アプリケーションの簡単なデータベースバックエンドのセットアップを実行します。この手順は、CloudFirestoreとRealtimeDatabaseの両方に適用されます。(注:進むにつれて、両方のプロセスの違いを強調します)
  • 基本的なコードを使用してFlutterアプリケーションをセットアップします。これは、ユーザーが投票するアプリケーションポイントのコアをサポートするために行います。したがって、両方のデータベースに、使用できるデータが事前に入力されます。このデータは、アプリケーションからデータベースに挿入されます。この場合のように、アドホックな手動プロセスを介しては挿入されません。
  • 単純な読み取りおよび書き込み操作を接続して実行する際のそれらの違いを示します
  • 次に、個別のクエリ機能に基づいてそれらがどのように異なるかを示します

CloudFirestore

Cloud FirestoreはNoSQLドキュメントデータベースであり、アプリのデータの保存、同期、クエリをグローバル規模で簡素化します。

これは、サーバーを用意する手間をかけずに、バックエンドをFlutterアプリに配置するための優れた方法です。Cloud Firestoreは、リアルタイムデータベースと比較すると、複雑なクエリ構造を可能にします。データは(ドキュメントとして)保存されるときに構造化されるため、リアルタイムデータベースと比較して、より面倒または不可能なクエリを実行できます。

この例では、すべてのアプリ間でデータを共有し、さまざまな場所でさまざまなメンバーが投じた投票の持続性を追跡できるバックエンドソースが必要になります。

Cloud Firestoreを使用すると、投票セッションに参加できるユーザー向けのコレクションを作成し、投票できる可能性のある決定のリストをグループ化できます。コレクションを作成するときは、Cloud Firestoreをアプリケーションに統合し、そのコレクションのデータを使用してFlutterウィジェットを構築します。Firestoreは細部のほとんどを処理し、永続的な情報の更新と既存のすべてのアプリインスタンスへの変更の中継を保証します。

Flutterアプリケーションの作成

先に進み、Firestoreで操作を実行するための新しいFlutterアプリケーションを作成します。

Firebaseプロジェクトの作成

まず、Flutterプロジェクトを作成します。

まず、アプリケーション用にFirebaseプロジェクトを設定する必要があります。これを行うには、Firebaseにアクセスして新しいプロジェクトを作成します。

アプリ名を使用しますvotersapp。次に、「続行」をクリックしてプロジェクトを作成します。(注:Google Analyticsを有効にすることは個人的な選択です)。

プロジェクトを作成したら、「続行」をクリックして、プロジェクトの個々のアプリを登録します。現在のページのAndroidアイコンをクリックして、プロジェクトをAndroidデバイスに登録します。iOSアプリケーションを登録する場合、または両方のプラットフォームを登録する場合、プロセスはほぼ同じです。

Androidパッケージ名フィールドのFlutterアプリケーションに移動します。会社名(逆ドメイン名)をコピーして入力します。これはandroidmanifest.xmlファイルにあります。

完了したら、をクリックして構成ファイルをダウンロードし、[次へ]をクリックします。

次に、Firebaseがアプリケーションの登録を完了して通信できるように、いくつかの基本的な構成を設定する必要があります。

以前にダウンロードしたgoogle-services.jsonファイルをドラッグして、android /app/ディレクトリに挿入します。

FirebaseGradleプラグインを設定します。FlutterプロジェクトのAndroidディレクトリにあるbuild.gradleファイルを開き、このコードを以下の依存関係に追加します。

classpath 'com.google.gms:google-services:4.3.10
{
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}

次に、android / app / build.gradleファイルを開き、apply pluginキーに「com.google.gms.google-services」を追加します。

次に、https: //pub.dev/packages/cloud_firestoreにアクセスし、Cloud Firestoreの最新バージョンを取得して、pubspec.YAMLファイルに追加します。

Flutterpub getを実行してプラグインを取得します。

次に、コンソールダッシュボードからCloudFirestoreを選択します。ビルド/ファイアストアデータベースで、「テストモード」を選択して有効にします。

次に、「Users」というコレクションを作成します。コレクションには、投票できる各ユーザーのドキュメントが含まれます。次に、4人のユーザーを入力します。「Ade」、「Bisi」、「David」、「Claire」。

これで、バックエンドがすべてセットアップされました。次に、Firebaseバックエンドと通信するためのアプリケーションが必要になります。FlutterアプリケーションでCloudFirestoreプラグインを使用します。

Flutterアプリケーション

Flutterアプリケーションでは、このチュートリアルのコアアイデアを示すスクリーンショットを表示します。

CloudFirestoreからの読み取り

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

Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();

 await Firebase.initializeApp();
 runApp(const 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',
 theme: ThemeData(
 primarySwatch: Colors.blue,
 ),
 home: const MyHomePage(title: 'Flutter Demo Home Page'),
 );
 }
}

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

 final String title;

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

class _MyHomePageState extends State<MyHomePage> {
 final Stream<QuerySnapshot> _usersStream =
 FirebaseFirestore.instance.collection('users').snapshots();

 @override
Widget build(BuildContext context) {
 return Scaffold(
 appBar: AppBar(
 title: Text(widget.title),
 ),
 body: SingleChildScrollView(
 child: Container(
 margin: EdgeInsets.symmetric(
  vertical: MediaQuery.of(context).size.height * 0.04,
  horizontal: MediaQuery.of(context).size.width * 0.04),
 child: Column(
  mainAxisAlignment: MainAxisAlignment.start,
  crossAxisAlignment: CrossAxisAlignment.start,
  children: <Widget>[
  const Text(
   'Enter user name',
  style: TextStyle(fontSize: 16),
  ),
  const SizedBox(
  height: 10,
  ),
  TextField(

  onChanged: (value) {
  //Do something with the user input.

  },
  decoration: const InputDecoration(
  hintText: 'Enter your password.',
  contentPadding:
   EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
  border: OutlineInputBorder(
   borderRadius: BorderRadius.all(Radius.circular(6.0)),
  ),
  ),
  ),

  , icon: Icon(Icons.add), label: Text('Add user')),
  const SizedBox(
  height: 20,
  ),
  StreamBuilder<QuerySnapshot>(
  stream: _usersStream,
  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(
   shrinkWrap: true,
   children:
   snapshot.data!.docs.map((DocumentSnapshot document) {
   Map<String, dynamic> data =
    document.data()! as Map<String, dynamic>;
   return ListTile(
   title: Text(data['name']),
   );
   }).toList(),
   );
  })
  ],
 ),
 ),
 ),
 );
}
}

コードスニペットの説明

上記のコードでは、Flutterアプリケーションに必要なプラグインをインポートしました。

(注:FirestoreにはFirebaseコアが必要なため、それをpubspec.YAMLファイルに追加し、アプリケーションにもインポートしました。)

以下のコードは、Firebaseをアプリに初期化します。補足として、ウィジェットを作成するとき、データベースにテキストフィールドと現在のユーザーのリストがあります。ウィジェットをでラップし、重複を避けるためにプロパティをSingleChildScrollView設定しました。ListView ShrinkWraptrue

WidgetsFlutterBinding.ensureInitialized();

await Firebase.initializeApp();

以下のコードは主要なパワーハウスです—CloudFirestoreからの読み取り機能を実行します。

final Stream<QuerySnapshot> _usersStream =
 FirebaseFirestore.instance.collection('users').snapshots();

ユーザーコレクションのインスタンスを取得し、それをStream<QuerySnapshot>変数に格納します。

以下のコードはFlutterウィジェットです。これにより、データベースのデータスナップショットに変更があった場合にウィジェットの状態を更新するストリームが作成されます。すべてのユーザーのリストが表示されます。

StreamBuilder<QuerySnapshot>(
  stream: _usersStream,
  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(
   shrinkWrap: true,
   children:
   snapshot.data!.docs.map((DocumentSnapshot document) {
   Map<String, dynamic> data =
    document.data()! as Map<String, dynamic>;
   return ListTile(
   title: Text(data['name']),
   );
   }).toList(),
   );
  })
  )

ファイヤーストア書き込み操作

書き込み操作を実行するには、最初にコレクションインスタンスと、ユーザーテキスト入力を保持する変数を作成します。例を次に示します。

CollectionReference users = FirebaseFirestore.instance.collection('users');
String name = '';

次に、CloudFirestoreを使用してデータベースにドキュメントを挿入する関数を作成します。

Future<void> addUser() {
 // Call the user's CollectionReference to add a new user
 return users
  .add({
  'name': name, // John Doe
 })
  .then((value) => print("User Added"))
  .catchError((error) => print("Failed to add user: $error"));
}

コードにボタンウィジェットを追加しonPressed、名前変数をテキストフィールドの内容で更新するように関数を設定しました。コードベースは次のようになります。

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

Future<void> main() async {
 WidgetsFlutterBinding.ensureInitialized();
 await Firebase.initializeApp();
 runApp(const 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',
  theme: ThemeData(
  primarySwatch: Colors.blue,
  ),
  home: const MyHomePage(title: 'Flutter Demo Home Page'),
 );
 }
}

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

 final String title;

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

class _MyHomePageState extends State<MyHomePage> {
 final Stream<QuerySnapshot> _usersStream =
  FirebaseFirestore.instance.collection('users').snapshots();

 CollectionReference users = FirebaseFirestore.instance.collection('users');

 String name = '';

 Future<void> addUser() {
 // Call the user's CollectionReference to add a new user
 return users
  .add({
  'name': name, // John Doe
 })
  .then((value) => print("User Added"))
  .catchError((error) => print("Failed to add user: $error"));
 }

 @override
 Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(
  title: Text(widget.title),
  ),
  body: SingleChildScrollView(
  child: Container(
   margin: EdgeInsets.symmetric(
    vertical: MediaQuery.of(context).size.height * 0.04,
    horizontal: MediaQuery.of(context).size.width * 0.04),
   child: Column(
   mainAxisAlignment: MainAxisAlignment.start,
   crossAxisAlignment: CrossAxisAlignment.start,
   children: <Widget>[
    const Text(
     'Enter user name',
    style: TextStyle(fontSize: 16),
    ),
    const SizedBox(
    height: 10,
    ),
    TextField(
    onChanged: (value) {
     //Do something with the user input.
     name = value;
    },
    decoration: const InputDecoration(
     hintText: 'Enter your password.',
     contentPadding:
      EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
     border: OutlineInputBorder(
     borderRadius: BorderRadius.all(Radius.circular(6.0)),
     ),
    ),
    ),
    const SizedBox(
    height: 5,
    ),
    ElevatedButton.icon(
     onPressed: (){
     addUser();
    }, icon: Icon(Icons.add), label: Text('Add user')),
    const SizedBox(
    height: 20,
    ),
    StreamBuilder<QuerySnapshot>(
     stream: _usersStream,
     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(
      shrinkWrap: true,
      children:
       snapshot.data!.docs.map((DocumentSnapshot document) {
      Map<String, dynamic> data =
       document.data()! as Map<String, dynamic>;
      return ListTile(
       title: Text(data['name']),
      );
      }).toList(),
     );
     })
   ],
   ),
  ),
  ),
 );
 }
}

その他のCloudFirestore関数は、
https ://firebase.flutter.dev/docs/firestore/usage/に一覧表示されています。

(注:Cloud Firestoreでは、フィルターをチェーンし、1つのクエリでプロパティのフィルター処理と並べ替えを組み合わせることができます。)

リアルタイムデータベース

Firebaseバックエンドプロジェクトの設定は、Cloud Firestoreで行ったものと似ていますが、データベースを選択するときに、FirestoreデータベースではなくRealtimeデータベースを選択する点が異なります。

Flutterアプリケーション

このセクションでは、CloudFirestoreとは異なるプラグインを使用します。したがって、このpubspec.YAMLファイルでは、Firebase_databaseを依存関係として追加します。Flutterアプリケーションでは、以下の手順に従う必要があります。

まず、Firebase_databaseをDartファイルにインポートします。

import 'package:firebase_database/firebase_database.dart';

次に、アプリケーションを初期化するために、以下のコードを使用します。

WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();

Realtime DatabaseはデータをJSONとして保存するため、を介してデータのノードにアクセスできることに注意してくださいDatabaseReference。たとえば、次のようにデータを保存すると、検索ごとに参照を作成できます。あれは:

{
 "users":
   “One”: {
  "name": "Ade"
 },
   “Two”: {
  "name": "Bisi"
 },
   ‘Three”: {
  "name": "David"
 },
   ‘Four”: {
  "name": "Claire"
 }
}

パスを指定することで、ノードへの参照を作成できます。

  • users /:「users」オブジェクト全体への参照を作成します
  • users / One:「One」ユーザーオブジェクトへの参照を作成します
  • users / Two / name:プロパティへの参照を作成します(「Bisi」の値を使用)
DatabaseReference ref = FirebaseDatabase.instance.ref("voters/1/users/1");

(注:パスを指定しない場合、参照はデータベースのルートを指します。)

リアルタイムデータベースへのデータの追加

このセクションでは、Firestoreで行ったのと同じように、新しいユーザーを追加してデータベースにデータを書き込みます。これを行うには、次の手順に従う必要があります。

まず、書き込みたいパスへの参照を作成します。

final refDataInstance = FirebaseDatabase.instance.reference().child('users');

以下に、Realtimeデータベースからデータを読み取り、新しいユーザーをデータベースに書き込む完全なコードを示します。

import 'package:firebase_database/ui/firebase_animated_list.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_database/firebase_database.dart';

Future<void> main() async {
 WidgetsFlutterBinding.ensureInitialized();

 var app = await Firebase.initializeApp();
 runApp(MaterialApp(
  title: 'Flutter Demo',
  theme: ThemeData(
  primarySwatch: Colors.blue,
  ),
  home: MyHomePage(app: app, title: 'Flutter Demo')));
}

class MyHomePage extends StatefulWidget {
 final FirebaseApp app;

 const MyHomePage({Key? key, required this.title, required this.app})
  : super(key: key);

 final String title;

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

class _MyHomePageState extends State<MyHomePage> {
 final refDataInstance = FirebaseDatabase.instance.reference().child('users');

 String name = '';

 @override
 Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(
  title: Text(widget.title),
  ),
  body: SingleChildScrollView(
  child: Container(
   height: MediaQuery.of(context).size.height,
   margin: EdgeInsets.symmetric(
    vertical: MediaQuery.of(context).size.height * 0.04,
    horizontal: MediaQuery.of(context).size.width * 0.04),
   child: Column(
   mainAxisAlignment: MainAxisAlignment.start,
   crossAxisAlignment: CrossAxisAlignment.start,
   children: <Widget>[
    const Text(
    'Enter user name',
    style: TextStyle(fontSize: 16),
    ),
    const SizedBox(
    height: 10,
    ),
    TextField(
    onChanged: (value) {
     //Do something with the user input.
     name = value;
    },
    decoration: const InputDecoration(
     hintText: 'Enter your password.',
     contentPadding:
      EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
     border: OutlineInputBorder(
     borderRadius: BorderRadius.all(Radius.circular(6.0)),
     ),
    ),
    ),
    const SizedBox(
    height: 5,
    ),
    ElevatedButton.icon(
     onPressed: () {
     // adds new user to DB
     refDataInstance.push().child('name').set(name).asStream();
     },
     icon: const Icon(Icons.add),
     label: const Text('Add user')),
    const SizedBox(
    height: 20,
    ),
    Flexible(
     child: FirebaseAnimatedList(
    shrinkWrap: true,
    query: refDataInstance,
    itemBuilder: (BuildContext context, DataSnapshot snapshot,
     Animation<double> animation, int index) {
     return ListTile(
     title: Text(snapshot.value['users']),
     );
    },
    )),
   ],
   ),
  ),
  ),
 );
 }
}

リアルタイムデータベースへの書き込み

以下の式を使用して、書き込み操作を実行します。データベース参照のインスタンスを使用して、ウィジェットのonTap関数にname変数の値を書き込むことができます。elevatedButton

refDataInstance.push().child('name').set(name).asStream();

データベースインスタンスからの読み取り

Firebaseのウィジェットを使用するとFirebaseAnimatedList、データベースを変更するたびにライブストリームの書き込みまたは読み取りを実行できます。

FirebaseAnimatedList(
 shrinkWrap: true,
 query: refDataInstance,
 itemBuilder: (BuildContext context, DataSnapshot snapshot,
  Animation<double> animation, int index) {
 return ListTile(
  title: Text(snapshot.value['users']),
 );
 },
)

(注:リアルタイムデータベースでは、複数ではなく1つのプロパティに対して、単一のクエリでデータをフィルタリングまたは並べ替えることができます。)

結論

Cloud Firestoreは、リアルタイムデータベースと比較して複雑なクエリ構造を可能にします。データは(ドキュメントとして)保存されるときに構造化されるため、CloudFirerstoreで面倒なクエリを実行できます。

リアルタイムデータベースのように複数のプロパティのみを使用するのではなく、1つのプロパティのみを使用して単一のクエリでデータをフィルタリングまたは並べ替えることを選択できます。Cloud Firestoreでは、フィルターをチェーンし、単一のクエリでプロパティのフィルタリングと並べ替えを組み合わせることができます。

データを降順でフェッチする場合、Cloud Firestoreは、Realtime Databaseがクエリ機能を提供しない場合に非常に便利です。また、複数の「where」メソッドをチェーンして、Cloud Firestoreでより具体的なクエリ(論理積)を作成することもできます。

users.whereEqualTo("name", "Bisi").whereEqualTo("vote", 0);

これらの理由から、Flutterアプリケーションに最適なクエリ機能を備えたデータベースを探す場合は、CloudFirestoreを強く推奨します。上記のいくつかのサンプルを使用して、CloudFirestoreがFirebaseの対応物をどのようにエッジングするかを見てきました。

ハッピーコーディング💻

リンク:https ://blog.logrocket.com/google-cloud-firestore-realtime-database-flutter/

#flutter  #google   #firestore 

What is GEEK

Buddha Community

FlutterのGoogleCloudFirestoreとRealtimeDatabase

FlutterのGoogleCloudFirestoreとRealtimeDatabase

Googleは、データの永続性を長期にわたって維持するためのサービスを提供しています。アプリケーションで使用されるデータは、必要なときに利用可能で、簡単にアクセスでき、できればアプリですぐに使用できるように構成されている必要があります。

CloudFirestoreとFirebaseRealtimeDatabaseは、Googleが提供する2つのサービスです。どちらもアプリケーションに必要なことを実行できますが、両者の間にはさまざまな違いがあります。これにより、実際には特定のアプリケーションタイプに最適になります。

この記事では、Flutterアプリケーションのクエリに適したデータベースを紹介します。はじめに、この記事の内容、使用例、前提条件、およびプロセスの概要を簡単に説明します。

カバーする内容

この記事では、以下について説明します。

  • FlutterアプリをCloudFirestoreとRealtimeDatabaseに別々に接続する方法
  • データクエリの観点からどのように差別化されているか

私たちの例

プラットフォームの登録ユーザーが特定のトピックや決定に投票できるアプリケーションを作成します。

使用するサンプルデータセットを使用すると、CloudFirestoreとRealtimeDatabaseの違いを次の2つの理由で紹介できます。

  • Flutterアプリケーションとの接続
  • 処理できるクエリ機能の違い

前提条件

  • 基本的なFlutterアプリケーションの作成方法に関する知識
  • NoSql/ドキュメントベースのデータストレージの概念に精通している
  • Flutterの外部にあるか、Flutterを使用しているかにかかわらず、CloudFirestoreまたはRealtimeDatabaseのいずれかを知っていることはプラスです

駆け抜ける

私たちのフローは次の構造を取ります:

  • アプリケーションの簡単なデータベースバックエンドのセットアップを実行します。この手順は、CloudFirestoreとRealtimeDatabaseの両方に適用されます。(注:進むにつれて、両方のプロセスの違いを強調します)
  • 基本的なコードを使用してFlutterアプリケーションをセットアップします。これは、ユーザーが投票するアプリケーションポイントのコアをサポートするために行います。したがって、両方のデータベースに、使用できるデータが事前に入力されます。このデータは、アプリケーションからデータベースに挿入されます。この場合のように、アドホックな手動プロセスを介しては挿入されません。
  • 単純な読み取りおよび書き込み操作を接続して実行する際のそれらの違いを示します
  • 次に、個別のクエリ機能に基づいてそれらがどのように異なるかを示します

CloudFirestore

Cloud FirestoreはNoSQLドキュメントデータベースであり、アプリのデータの保存、同期、クエリをグローバル規模で簡素化します。

これは、サーバーを用意する手間をかけずに、バックエンドをFlutterアプリに配置するための優れた方法です。Cloud Firestoreは、リアルタイムデータベースと比較すると、複雑なクエリ構造を可能にします。データは(ドキュメントとして)保存されるときに構造化されるため、リアルタイムデータベースと比較して、より面倒または不可能なクエリを実行できます。

この例では、すべてのアプリ間でデータを共有し、さまざまな場所でさまざまなメンバーが投じた投票の持続性を追跡できるバックエンドソースが必要になります。

Cloud Firestoreを使用すると、投票セッションに参加できるユーザー向けのコレクションを作成し、投票できる可能性のある決定のリストをグループ化できます。コレクションを作成するときは、Cloud Firestoreをアプリケーションに統合し、そのコレクションのデータを使用してFlutterウィジェットを構築します。Firestoreは細部のほとんどを処理し、永続的な情報の更新と既存のすべてのアプリインスタンスへの変更の中継を保証します。

Flutterアプリケーションの作成

先に進み、Firestoreで操作を実行するための新しいFlutterアプリケーションを作成します。

Firebaseプロジェクトの作成

まず、Flutterプロジェクトを作成します。

まず、アプリケーション用にFirebaseプロジェクトを設定する必要があります。これを行うには、Firebaseにアクセスして新しいプロジェクトを作成します。

アプリ名を使用しますvotersapp。次に、「続行」をクリックしてプロジェクトを作成します。(注:Google Analyticsを有効にすることは個人的な選択です)。

プロジェクトを作成したら、「続行」をクリックして、プロジェクトの個々のアプリを登録します。現在のページのAndroidアイコンをクリックして、プロジェクトをAndroidデバイスに登録します。iOSアプリケーションを登録する場合、または両方のプラットフォームを登録する場合、プロセスはほぼ同じです。

Androidパッケージ名フィールドのFlutterアプリケーションに移動します。会社名(逆ドメイン名)をコピーして入力します。これはandroidmanifest.xmlファイルにあります。

完了したら、をクリックして構成ファイルをダウンロードし、[次へ]をクリックします。

次に、Firebaseがアプリケーションの登録を完了して通信できるように、いくつかの基本的な構成を設定する必要があります。

以前にダウンロードしたgoogle-services.jsonファイルをドラッグして、android /app/ディレクトリに挿入します。

FirebaseGradleプラグインを設定します。FlutterプロジェクトのAndroidディレクトリにあるbuild.gradleファイルを開き、このコードを以下の依存関係に追加します。

classpath 'com.google.gms:google-services:4.3.10
{
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}

次に、android / app / build.gradleファイルを開き、apply pluginキーに「com.google.gms.google-services」を追加します。

次に、https: //pub.dev/packages/cloud_firestoreにアクセスし、Cloud Firestoreの最新バージョンを取得して、pubspec.YAMLファイルに追加します。

Flutterpub getを実行してプラグインを取得します。

次に、コンソールダッシュボードからCloudFirestoreを選択します。ビルド/ファイアストアデータベースで、「テストモード」を選択して有効にします。

次に、「Users」というコレクションを作成します。コレクションには、投票できる各ユーザーのドキュメントが含まれます。次に、4人のユーザーを入力します。「Ade」、「Bisi」、「David」、「Claire」。

これで、バックエンドがすべてセットアップされました。次に、Firebaseバックエンドと通信するためのアプリケーションが必要になります。FlutterアプリケーションでCloudFirestoreプラグインを使用します。

Flutterアプリケーション

Flutterアプリケーションでは、このチュートリアルのコアアイデアを示すスクリーンショットを表示します。

CloudFirestoreからの読み取り

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

Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();

 await Firebase.initializeApp();
 runApp(const 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',
 theme: ThemeData(
 primarySwatch: Colors.blue,
 ),
 home: const MyHomePage(title: 'Flutter Demo Home Page'),
 );
 }
}

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

 final String title;

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

class _MyHomePageState extends State<MyHomePage> {
 final Stream<QuerySnapshot> _usersStream =
 FirebaseFirestore.instance.collection('users').snapshots();

 @override
Widget build(BuildContext context) {
 return Scaffold(
 appBar: AppBar(
 title: Text(widget.title),
 ),
 body: SingleChildScrollView(
 child: Container(
 margin: EdgeInsets.symmetric(
  vertical: MediaQuery.of(context).size.height * 0.04,
  horizontal: MediaQuery.of(context).size.width * 0.04),
 child: Column(
  mainAxisAlignment: MainAxisAlignment.start,
  crossAxisAlignment: CrossAxisAlignment.start,
  children: <Widget>[
  const Text(
   'Enter user name',
  style: TextStyle(fontSize: 16),
  ),
  const SizedBox(
  height: 10,
  ),
  TextField(

  onChanged: (value) {
  //Do something with the user input.

  },
  decoration: const InputDecoration(
  hintText: 'Enter your password.',
  contentPadding:
   EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
  border: OutlineInputBorder(
   borderRadius: BorderRadius.all(Radius.circular(6.0)),
  ),
  ),
  ),

  , icon: Icon(Icons.add), label: Text('Add user')),
  const SizedBox(
  height: 20,
  ),
  StreamBuilder<QuerySnapshot>(
  stream: _usersStream,
  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(
   shrinkWrap: true,
   children:
   snapshot.data!.docs.map((DocumentSnapshot document) {
   Map<String, dynamic> data =
    document.data()! as Map<String, dynamic>;
   return ListTile(
   title: Text(data['name']),
   );
   }).toList(),
   );
  })
  ],
 ),
 ),
 ),
 );
}
}

コードスニペットの説明

上記のコードでは、Flutterアプリケーションに必要なプラグインをインポートしました。

(注:FirestoreにはFirebaseコアが必要なため、それをpubspec.YAMLファイルに追加し、アプリケーションにもインポートしました。)

以下のコードは、Firebaseをアプリに初期化します。補足として、ウィジェットを作成するとき、データベースにテキストフィールドと現在のユーザーのリストがあります。ウィジェットをでラップし、重複を避けるためにプロパティをSingleChildScrollView設定しました。ListView ShrinkWraptrue

WidgetsFlutterBinding.ensureInitialized();

await Firebase.initializeApp();

以下のコードは主要なパワーハウスです—CloudFirestoreからの読み取り機能を実行します。

final Stream<QuerySnapshot> _usersStream =
 FirebaseFirestore.instance.collection('users').snapshots();

ユーザーコレクションのインスタンスを取得し、それをStream<QuerySnapshot>変数に格納します。

以下のコードはFlutterウィジェットです。これにより、データベースのデータスナップショットに変更があった場合にウィジェットの状態を更新するストリームが作成されます。すべてのユーザーのリストが表示されます。

StreamBuilder<QuerySnapshot>(
  stream: _usersStream,
  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(
   shrinkWrap: true,
   children:
   snapshot.data!.docs.map((DocumentSnapshot document) {
   Map<String, dynamic> data =
    document.data()! as Map<String, dynamic>;
   return ListTile(
   title: Text(data['name']),
   );
   }).toList(),
   );
  })
  )

ファイヤーストア書き込み操作

書き込み操作を実行するには、最初にコレクションインスタンスと、ユーザーテキスト入力を保持する変数を作成します。例を次に示します。

CollectionReference users = FirebaseFirestore.instance.collection('users');
String name = '';

次に、CloudFirestoreを使用してデータベースにドキュメントを挿入する関数を作成します。

Future<void> addUser() {
 // Call the user's CollectionReference to add a new user
 return users
  .add({
  'name': name, // John Doe
 })
  .then((value) => print("User Added"))
  .catchError((error) => print("Failed to add user: $error"));
}

コードにボタンウィジェットを追加しonPressed、名前変数をテキストフィールドの内容で更新するように関数を設定しました。コードベースは次のようになります。

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

Future<void> main() async {
 WidgetsFlutterBinding.ensureInitialized();
 await Firebase.initializeApp();
 runApp(const 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',
  theme: ThemeData(
  primarySwatch: Colors.blue,
  ),
  home: const MyHomePage(title: 'Flutter Demo Home Page'),
 );
 }
}

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

 final String title;

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

class _MyHomePageState extends State<MyHomePage> {
 final Stream<QuerySnapshot> _usersStream =
  FirebaseFirestore.instance.collection('users').snapshots();

 CollectionReference users = FirebaseFirestore.instance.collection('users');

 String name = '';

 Future<void> addUser() {
 // Call the user's CollectionReference to add a new user
 return users
  .add({
  'name': name, // John Doe
 })
  .then((value) => print("User Added"))
  .catchError((error) => print("Failed to add user: $error"));
 }

 @override
 Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(
  title: Text(widget.title),
  ),
  body: SingleChildScrollView(
  child: Container(
   margin: EdgeInsets.symmetric(
    vertical: MediaQuery.of(context).size.height * 0.04,
    horizontal: MediaQuery.of(context).size.width * 0.04),
   child: Column(
   mainAxisAlignment: MainAxisAlignment.start,
   crossAxisAlignment: CrossAxisAlignment.start,
   children: <Widget>[
    const Text(
     'Enter user name',
    style: TextStyle(fontSize: 16),
    ),
    const SizedBox(
    height: 10,
    ),
    TextField(
    onChanged: (value) {
     //Do something with the user input.
     name = value;
    },
    decoration: const InputDecoration(
     hintText: 'Enter your password.',
     contentPadding:
      EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
     border: OutlineInputBorder(
     borderRadius: BorderRadius.all(Radius.circular(6.0)),
     ),
    ),
    ),
    const SizedBox(
    height: 5,
    ),
    ElevatedButton.icon(
     onPressed: (){
     addUser();
    }, icon: Icon(Icons.add), label: Text('Add user')),
    const SizedBox(
    height: 20,
    ),
    StreamBuilder<QuerySnapshot>(
     stream: _usersStream,
     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(
      shrinkWrap: true,
      children:
       snapshot.data!.docs.map((DocumentSnapshot document) {
      Map<String, dynamic> data =
       document.data()! as Map<String, dynamic>;
      return ListTile(
       title: Text(data['name']),
      );
      }).toList(),
     );
     })
   ],
   ),
  ),
  ),
 );
 }
}

その他のCloudFirestore関数は、
https ://firebase.flutter.dev/docs/firestore/usage/に一覧表示されています。

(注:Cloud Firestoreでは、フィルターをチェーンし、1つのクエリでプロパティのフィルター処理と並べ替えを組み合わせることができます。)

リアルタイムデータベース

Firebaseバックエンドプロジェクトの設定は、Cloud Firestoreで行ったものと似ていますが、データベースを選択するときに、FirestoreデータベースではなくRealtimeデータベースを選択する点が異なります。

Flutterアプリケーション

このセクションでは、CloudFirestoreとは異なるプラグインを使用します。したがって、このpubspec.YAMLファイルでは、Firebase_databaseを依存関係として追加します。Flutterアプリケーションでは、以下の手順に従う必要があります。

まず、Firebase_databaseをDartファイルにインポートします。

import 'package:firebase_database/firebase_database.dart';

次に、アプリケーションを初期化するために、以下のコードを使用します。

WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();

Realtime DatabaseはデータをJSONとして保存するため、を介してデータのノードにアクセスできることに注意してくださいDatabaseReference。たとえば、次のようにデータを保存すると、検索ごとに参照を作成できます。あれは:

{
 "users":
   “One”: {
  "name": "Ade"
 },
   “Two”: {
  "name": "Bisi"
 },
   ‘Three”: {
  "name": "David"
 },
   ‘Four”: {
  "name": "Claire"
 }
}

パスを指定することで、ノードへの参照を作成できます。

  • users /:「users」オブジェクト全体への参照を作成します
  • users / One:「One」ユーザーオブジェクトへの参照を作成します
  • users / Two / name:プロパティへの参照を作成します(「Bisi」の値を使用)
DatabaseReference ref = FirebaseDatabase.instance.ref("voters/1/users/1");

(注:パスを指定しない場合、参照はデータベースのルートを指します。)

リアルタイムデータベースへのデータの追加

このセクションでは、Firestoreで行ったのと同じように、新しいユーザーを追加してデータベースにデータを書き込みます。これを行うには、次の手順に従う必要があります。

まず、書き込みたいパスへの参照を作成します。

final refDataInstance = FirebaseDatabase.instance.reference().child('users');

以下に、Realtimeデータベースからデータを読み取り、新しいユーザーをデータベースに書き込む完全なコードを示します。

import 'package:firebase_database/ui/firebase_animated_list.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_database/firebase_database.dart';

Future<void> main() async {
 WidgetsFlutterBinding.ensureInitialized();

 var app = await Firebase.initializeApp();
 runApp(MaterialApp(
  title: 'Flutter Demo',
  theme: ThemeData(
  primarySwatch: Colors.blue,
  ),
  home: MyHomePage(app: app, title: 'Flutter Demo')));
}

class MyHomePage extends StatefulWidget {
 final FirebaseApp app;

 const MyHomePage({Key? key, required this.title, required this.app})
  : super(key: key);

 final String title;

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

class _MyHomePageState extends State<MyHomePage> {
 final refDataInstance = FirebaseDatabase.instance.reference().child('users');

 String name = '';

 @override
 Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(
  title: Text(widget.title),
  ),
  body: SingleChildScrollView(
  child: Container(
   height: MediaQuery.of(context).size.height,
   margin: EdgeInsets.symmetric(
    vertical: MediaQuery.of(context).size.height * 0.04,
    horizontal: MediaQuery.of(context).size.width * 0.04),
   child: Column(
   mainAxisAlignment: MainAxisAlignment.start,
   crossAxisAlignment: CrossAxisAlignment.start,
   children: <Widget>[
    const Text(
    'Enter user name',
    style: TextStyle(fontSize: 16),
    ),
    const SizedBox(
    height: 10,
    ),
    TextField(
    onChanged: (value) {
     //Do something with the user input.
     name = value;
    },
    decoration: const InputDecoration(
     hintText: 'Enter your password.',
     contentPadding:
      EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
     border: OutlineInputBorder(
     borderRadius: BorderRadius.all(Radius.circular(6.0)),
     ),
    ),
    ),
    const SizedBox(
    height: 5,
    ),
    ElevatedButton.icon(
     onPressed: () {
     // adds new user to DB
     refDataInstance.push().child('name').set(name).asStream();
     },
     icon: const Icon(Icons.add),
     label: const Text('Add user')),
    const SizedBox(
    height: 20,
    ),
    Flexible(
     child: FirebaseAnimatedList(
    shrinkWrap: true,
    query: refDataInstance,
    itemBuilder: (BuildContext context, DataSnapshot snapshot,
     Animation<double> animation, int index) {
     return ListTile(
     title: Text(snapshot.value['users']),
     );
    },
    )),
   ],
   ),
  ),
  ),
 );
 }
}

リアルタイムデータベースへの書き込み

以下の式を使用して、書き込み操作を実行します。データベース参照のインスタンスを使用して、ウィジェットのonTap関数にname変数の値を書き込むことができます。elevatedButton

refDataInstance.push().child('name').set(name).asStream();

データベースインスタンスからの読み取り

Firebaseのウィジェットを使用するとFirebaseAnimatedList、データベースを変更するたびにライブストリームの書き込みまたは読み取りを実行できます。

FirebaseAnimatedList(
 shrinkWrap: true,
 query: refDataInstance,
 itemBuilder: (BuildContext context, DataSnapshot snapshot,
  Animation<double> animation, int index) {
 return ListTile(
  title: Text(snapshot.value['users']),
 );
 },
)

(注:リアルタイムデータベースでは、複数ではなく1つのプロパティに対して、単一のクエリでデータをフィルタリングまたは並べ替えることができます。)

結論

Cloud Firestoreは、リアルタイムデータベースと比較して複雑なクエリ構造を可能にします。データは(ドキュメントとして)保存されるときに構造化されるため、CloudFirerstoreで面倒なクエリを実行できます。

リアルタイムデータベースのように複数のプロパティのみを使用するのではなく、1つのプロパティのみを使用して単一のクエリでデータをフィルタリングまたは並べ替えることを選択できます。Cloud Firestoreでは、フィルターをチェーンし、単一のクエリでプロパティのフィルタリングと並べ替えを組み合わせることができます。

データを降順でフェッチする場合、Cloud Firestoreは、Realtime Databaseがクエリ機能を提供しない場合に非常に便利です。また、複数の「where」メソッドをチェーンして、Cloud Firestoreでより具体的なクエリ(論理積)を作成することもできます。

users.whereEqualTo("name", "Bisi").whereEqualTo("vote", 0);

これらの理由から、Flutterアプリケーションに最適なクエリ機能を備えたデータベースを探す場合は、CloudFirestoreを強く推奨します。上記のいくつかのサンプルを使用して、CloudFirestoreがFirebaseの対応物をどのようにエッジングするかを見てきました。

ハッピーコーディング💻

リンク:https ://blog.logrocket.com/google-cloud-firestore-realtime-database-flutter/

#flutter  #google   #firestore