【flutter】firebaseをモデル層から読んでview層で表示する方法

本日は、firebaseで取得しているデータをmodel層を通して取得を行う。

<img width="1440" alt="スクリーンショット 2020-06-28 14.01.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612642/0fff649a-db1c-b828-9d08-01c2a78bd69a.png">
取得したいデータは上記のような構造になっている。

始めにfirebaseでのデータを格納するクラスを作成する

```book.dart
class Book{
  Book(this.title);
  String title;
}
 ```
これでfirebaseのデータをリスト化するBookクラスを作成が完了。

次にbook_list_model.dartをコーディングしていく。

```book_list_model.dart
class BookListModel extends ChangeNotifier {
 List<Book>books = [];

 Future fetchBooks() async {
  final docs = await Firestore.instance.collection('books').getDocuments();
  final books = docs.documents.map((doc) => Book(doc['title'])).toList();
  this.books = books;
  notifyListeners();
 }
}
```

```dart
class BookListModel extends ChangeNotifier {
 List<Book>books = [];//先ほどのBookクラスを格納する変数booksを作成
}
```

```dart
 Future fetchBooks() async {
  final docs = await Firestore.instance.collection('books').getDocuments();
```
始めにfirestoreのbooksデータを取得し変数docsに変換する。

```dart
final books = docs.documents.map((doc) => Book(doc['title'])).toList();
```

取得したdocsデータをmapに変換する。

```
map((doc) => Book(doc['title'])).toList();
this.books = books;
```
この部分では、データ全体であるdocsの内の一つ分のデータであるdocをmap化し新しいリストを作成すし、
変数bookを先ほど作成したListであるbooksに変換する。

これでデータを分割して格納することが出来た。
次に、view層では、

```book_list.dart

class BookListPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<BookListModel>(
     create: (context)=>BookListModel()..fetchBooks(),
      child: Scaffold(
        appBar: AppBar(
          title: Text('kboyのflutter'),
        ),
        body:Consumer<BookListModel>(
          builder: (context,model,child) {
            final books=model.books;
            final listTiles =books
                .map((book) => ListTile(
              title:Text(book.title),))
                .toList();
            return ListView(
             children: listTiles,
            );
          }
        ),
      ),
    );
  }
}
```

のようなコードを記載する。
最初に、

```dart
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<BookListModel>(
     create: (context)=>BookListModel()..fetchBooks(),
```

```
 create: (context)=>BookListModel()..fetchBooks(),
```

このようにすることでBookListPageが回ったタイミングでfetchBooks（）がまわるようになる。

```dart
body:Consumer<BookListModel>(
          builder: (context,model,child) {
            final books=model.books;
            final listTiles =books
                .map((book) => ListTile(
              title:Text(book.title),))
                .toList();
            return ListView(
             children: listTiles,
            );
          }
```

```dart
final books=model.books; //先ほどmodel層で作成したbooksを再度booksへ変換
final listTiles =books.map((book) => ListTile(
                                  title:Text(book.title),))
                                  .toList();
```
こちらでbooksをListTileにて一つ一つをリスト化するようなプログラムを作成する。

```
return ListView(
             children: listTiles,
            );
```
最後にこれらの取得したデータをListViewとして表示を行う。

これでデータが表示されるようになる。


サンプルコード
https://github.com/muscleyukou/kboy_flutter_practice


追記
こちらのコードはkboyさんのflutter大学を元に学習を行なっております。

参考動画
【Flutter実践】ProviderパターンでModelを作成する（iOS/Androidアプリ開発,プログラミング）
https://www.youtube.com/watch?v=iN2IjSQR7Fs&t=1047s