🔨

【Flutter & FireStore】Modelを作成して、データの一覧を取得 する

2021/07/09に公開

今回は、firestoreからデータを取得する方法を書いておきます。
firebaseとの連携方法については、他にもいろいろ記事があるので割愛します。
今回は商品の一覧を取得するという例で書いていきます。(コード上では商品をproductと書きます)

ProductModelを作成する(商品単体のモデル)

firestoreからデータを取得するときだけではなく、データベースからデータを取得したいときは基本的にModelというものを用意します。
Modelとは、あるモノの特性を変数として定義したクラスのことで、プログラム上で、「モノ自体」のような役割を担います。
例えば、ECサイトで商品データをデータベースに入れて、それを取得できるようにしたいぞ、と思ったときには、商品の特性である・商品名・値段をひとつのクラスとして定義しておきます。これによって、データベースからデータを取得する際に、それぞれのデータを別々で取得するのではなく、商品は商品として、データをまとめておくことができます。

Flutter(dart)だと次のように定義します。

class ProductModel {
  String productName, productPrice;
  ProductModel(
    this.productName,
    this.productPrice,
  );
}

今回のケースでは、商品名と値段だけを定義しましたが、本来であれば、商品のID、詳細、在庫数、商品カテゴリなど、多くの情報が入ると思います。

ProductListModelを作成する(商品の全体のモデル)

商品全体のモデルというのは何かというと、先ほど作ったProductModelが1つの商品をリストにしたモデルになります。
イメージはこんな感じです。

ProductListModel→ [商品1,商品2,商品3,商品4...]

実際のコードはこんな感じです。

class ProductListModel{
  List<ProductModel> products = [];
}

これは、List型の変数の中身は<ProductModel>(さっき作った商品モデル)で、名前は”products”です。という定義です。

Firestoreからデータを取得し、ProductListModelの中に入れる

ProductListModelにFireStoreからデータを取得する関数を追加します。
今回、firestoreのデータ構造は、
コレクション : products
ドキュメント : product1
フィールド : name:"aaa",price:'1000'
のようになっており、ドキュメントの部分が其れぞの商品のリストのような形になっています。

class ProductListModel extends ChangeNotifier {
  List<ProductModel> products = [];

  Future getProducts() async {
    collection =
        await FirebaseFirestore.instance.collection('products').get();
    products = collection.docs
        .map((doc) => ProductModel(
            doc['name'],doc['price']))
        .toList();
    this.products = products;
    notifyListeners();
  }
}

1.Future型の返り値を返す関数を定義

追加部分を一番最初を見ると、Future getProducts()と書いてあります。
これは、Futureというデータ型を持った値を返す、getProductという関数ですよ。という定義です。

2.ドキュメントを取得

collection =
        await FirebaseFirestore.instance.collection('products').get();

firestoreに格納されている'products'というコレクションから全てのデータを取得しています。

3. 1つ1つの商品のデータを取得し、配列にする

  1. では、商品データが入っている入れ物を取得したので、そこから、1つ1つデータを取り出して、配列として格納していく必要があります。ここで出てくるのが、序盤に作ったProductModelです。

firestoreから取得したデータをProductModelにいれて、それを配列に入れていきます。
要は、firestoreのデータのままだとつかえないから、アプリ内で定義した形でコピーしてこようという話です。

products = collection.docs
        .map((doc) => ProductModel(
            doc['name'],doc['price']))
        .toList();

collectionにドキュメントのリストが入っているので、それをdocsで取得
→ map()でそれを一つずつ操作する(ドキュメントのリスト内のドキュメントを一つ抜きずつ抜き出してくれる)
→ map()で抜き出したデータを使って、ProductModelから商品オブジェクトを作成し、toList()で配列型にする。

4. 作った商品リストをProductListModel内の変数に格納

	this.products = products; //左辺はModel内の変数、右辺はfirebaseから値をとってきた変数

同じ変数名なんてわかりづらいと思うかもしれませんが、このような場合は同じ変数名で書くことが一般的なので、それに則りました。

5. notifyListeners()をかく

これはおまじないのような物です。notifyという名前の通り、「変化に気づいて!」という意味です。(多分)

このモデルでは、FireStoreからデータを取得する前と、取得した後では値が変わります。
最初は空だった配列に、データが入るので。

その変化に気付いたFlutterくんが、自動で変更後の値を表示してくれるというための1文です。

データの取得は完了

データの取得はできましたが、最も肝心な取得したデータの表示が残っています。
しかしこの記事が長くなってしまったので、続きは別の記事で書いておきます。

Discussion