「[実践]FlutterとFirebaseを使ったアプリ開発」を実践する

# はじめに
<img width=300 src="https://m.media-amazon.com/images/I/51UEH-9pDUL.jpg">
Flutterで、firebaseを用いたアプリ開発をしたいので、勉強用に買った本でアプリを一つ作ってみる。
[flutterの勉強サイト](https://www.flutter-study.dev/introduction/about-flutter)を運営している著者の本。サイトだけ見ても勉強できると思うが、調べるのが面倒なので本を買って本の中身を一通りやってみることにする。
新しく学べたことをメモ程度に書いていくだけ。

ちなみに作成物は以下のgithub repositoryにあげています。

https://github.com/ninoko1995/FlutterFirebaseDemo

# 1章: FlutterとFirebaseの概要
特に得るものなし。

# 2章: 設計と環境設定。
設計：画面の遷移、画面に必要な機能、機能の実現に必要な処理、firebaseとのやりとり、などを図などで書いてみること。

既存の環境は以下のような感じ。
ちょっと本のバージョンと違うが、このまま進める。

```
$ flutter --version
  ╔════════════════════════════════════════════════════════════════════════════╗
  ║ A new version of Flutter is available!                                     ║
  ║                                                                            ║
  ║ To update to the latest version, run "flutter upgrade".                    ║
  ╚════════════════════════════════════════════════════════════════════════════╝


Flutter 2.2.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision f4abaa0735 (3 months ago) • 2021-07-01 12:46:11 -0700
Engine • revision 241c87ad80
Tools • Dart 2.13.4
```

ローカル及びFirebaseでそれぞれアプリを作成して、2章終了。

# 3章: UIの作成
## 3-1:ログイン画面の実装
- TextFormFieldの簡単な記述。
- TextFormFieldへのvalidationの付け方。

**実装後のスクリーンショット**
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/d121e0e2-5aec-60e3-6ef4-561a4ffef61f.png"><img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/9087620a-503e-103b-8d8e-c01cf3c8c97f.png">


## 3-2: 画像一覧画面の実装
- Navigatorの説明がちょっとある。
- PageControllerの使い方のコードも参考になるかも。
- GridViewの使い方。

**実装後のスクリーンショット**
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/87ca7568-3a2d-4110-97e8-488da187b55e.png">


## 3-3: 画像詳細画面
- BoxDecorationの使い方
- widgetの引数で、変数だけじゃなく関数も渡せる！(コールバック関数)

<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/95625295-3228-9e64-63d8-4be2a1423136.gif">

ちなみに、iOSだと画面の上下左右にsafeareaがあり、タップできない空間となっている。
そこにボタンが重なってしまうとよくないので、`SafeArea`のwidgetを用いて修正した。

<img width=350 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/333cf40a-cf57-096d-e18a-40bebf557d85.png">


## 3-4: この章のまとめ
この章で勉強したWidgetは以下。
どんなWidgetを使えばいいかとかは、勉強しはじめの時はわからんかったから役に立った。

Widgetの一覧は以下。

https://api.flutter.dev/flutter/widgets/widgets-library.html

以下のキーワードで検索するとより詳しく知れる。
- Form
- TextFirnField
- Navigator
- PageView
- BottomNavigationBar
- GridView
- Image


これで、UIの部分は完了！

# 4章: ログイン機能の実装
ここからは、Firebaseと接続したりして、実際の挙動を実装！

## 4-1: FlutterとFirebaseの連携
必要な準備

- Firebase構成ファイルをソースコードに反映(Android/iOS)
- Firebase用ライブラリをインストール
- Firebase初期化処理を入れる

**Firebase構成ファイルをソースコードに反映(Android)**
本に書いてある方法及び、Firebaseで指示される方法だけだと、以下のようなエラーが発生してしまいます。

```
Cannot resolve symbol 'Properties'
Cannot resolve symbol 'GradleException'
```

これを解決するために、以下のサイトに従って処理を行います。

https://moimoiblog.com/programing/flutter-cannot-resolve-symbol-properties/

**初期化処理**
非同期処理(Future)はawaitで処理が終わるのを待つことができる。
ただし、awaitを使うときは関数にasyncをつける必要がある。

## 4-2: Authenticationを準備する
Firebase側で色々認証方法が選べるので、メールアドレス以外にも色々試してみたい。
Twitterとgoogleは少なくとも今後実装したい。

![スクリーンショット 2021-10-13 23.56.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/fafd5867-04e0-0f87-2cbd-e42cc92c8f64.png)

## 4-3: 実際にアプリから新規登録する
FirebaseAuthを用いたsignUpの方法。
複雑な処理はライブラリーが行ってくれる。
エラー時のダイアログ表示も簡単に行えるっぽい。

ここまでやってアプリを起動してみると、アプリを立ち上げる途中に`pod install`の部分でエラーが出て落ちてしまった。
色々調べて、iOSの最低バージョンを上げるとエラーがなくなった。

https://github.com/flutter/flutter/issues/32389

動くようになったのちに、アプリから新規登録したらきちんとユーザが登録されていた！
![スクリーンショット_2021-10-14_0_53_27-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/269b3fc8-a942-2dad-c6ed-0951b404e1a1.jpeg)

適当なメールアドレスや登録してあるメールアドレスはきちんと弾いてくれるっぽい。めちゃ良い！
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/9aeadeb7-b07b-31a5-177c-3b2cd21cdad0.png"> <img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/390be27e-cf0f-8715-e2fc-92759da0e04d.png">

## 4-4/5/6: ログアウト/ログイン/初期画面切り替え
FirebaseAuthのメソッドを使うと、ログインログアウトも簡単！！

## 4-7: 4章まとめ

- FirebaseのAuthenticationを使うと、新規登録・ログイン・ログアウト・ログイン状態管理が簡単に実装できる！
- TextFormFieldの入力内容を取得するには、TextEditingControllerを使う！

<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/3e1b901c-92cc-405e-c907-0f943ae7a5c6.gif">

# 5章: 画像を管理する
`file_picker`を用いてスマホ内の画像にアクセス
`firebase_storage`を用いて選択されたものをCloud Storageに保存
`cloud_firestore`を用いて保存された画像の保存先URLなどをデータベースに保存・呼び出し


![スクリーンショット 2021-10-14 2.49.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/e6780979-b500-6308-3c78-95659599c3ed.png)
![スクリーンショット 2021-10-14 2.50.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/cf0478df-9d7c-57bd-506f-42998a6aebb6.png)
<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/1f636686-060a-dc94-ecfc-771774cab251.png">

# 6章: アーキテクチャを整える
## 6-1: モデルとレポジトリの導入
外部(ここではfirebase)とやりとりするためのレポジトリ層
データを受け渡しするためのデータモデル

ちゃんとアーキテクチャ設計とか学ぼう。

## 6-2: 状態管理
`flutter_riverpod`を用いる。

Providerの種類

- StateProvider: 更新可能なデータを渡す。
- StreamProvider: Streamをデータとして渡す。
- ScopedProvider: 状況に応じてデータを切り替える。

データ取得方法の種類

- ConsumerWidget: これを継承したWidgetを用いると、buildの中でデータを受け取れる。
- Consumer: consumerのコールバックからデータを受け取れる。
- context.read(): ボタンをタップした時など、その時点のデータを受け取れる。

文章で書いてもよくわからないので、実際のコードを見て利用方法を理解すべし。

## 6-3: 削除・お気に入り機能の追加実装
ボタンタップによりデータを更新・削除する処理。
モデルインスタンスを更新するのではなく、値を書き換えたインスタンスを新たに作成してfirestoreに保存する。

## 6-4: 画像共有機能
`share`を用いる。

# 7章: アクセス制御
不正アクセスを防ぐため、Cloud Firestore/Cloud Storageに存在するセキュリティルールと呼ばれる仕組みを用いる。


# まとめ
これで、以下のアプリが完成した。
<img width=250 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/65c516aa-2c31-01ec-3be5-2b8e06414cf2.png"><img width=250 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/6ea52723-6186-185a-6ddf-d87c1ff93672.png"><img width=250 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/795f0f20-b6f2-94b1-d4bf-6669c426728b.png"><img width=250 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/b4557808-36d2-1532-cb5c-21514f0bef3f.png"><img width=250 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/8e203e50-db80-1d4a-39b0-bc5b45f27f9e.png">

今後は、以下を実装していく。

- Twitter/Gmail連携のユーザ登録・ログイン
- 他のユーザの投稿が見られるようなセキュリティルールの記述
- 地点データなどの他の種類のデータの保存
- 多:多のデータの結びつきの実現
- google admobによる広告の実装