Flutterの学習方法

# 1. はじめに
こんにちは、
[株式会社エーエルジェイ](https://www.al-j.co.jp/)の福嶋です。

今回は、沖縄の名護でやんばるハッカソンというFlutterを用いてアプリ開発を行う
イベントのメンターをする事になり、
Flutter未経験の私が当日までにFlutterの知識を身につけなければならず、
どのようなプロセスで学習をしたかを備忘録として残そうと思います。
(誰かの参考にされば幸いです。)

ちなみにイベントの詳細は以下です。

https://prtimes.jp/main/html/rd/p/000000001.000135736.html

# 2. 学習の進め方
まず、私の前提条件として

- Unityでのモバイルアプリ開発経験あり
- Android Studioでのネイティブアプリ開発経験あり

という経歴のため、モバイル開発のある程度の前提条件はあるものとします。
(3年前だから結構忘れてますが、、)

　
学習の進め方としては、まず全体の特徴を掴むところから始めます。

- フレームワークの仕組み
- 言語仕様

また、Flutterアプリ作成をハンズオンで理解するため、以下をゴール設定として習得しようと思います。
1.  画面を2画面以上作る
【観点】
    - 画面作成方法
    - 画面遷移方法
        - データの受け渡し
        - 状態管理
2.  ビジネスロジックがあるサンプルアプリを作る
【観点】
    - ディレクトリ構造の把握
    - メソッドの書き方・呼び出しのお作法
3. データを記録するサンプルアプリを作る
【観点】
    - データの永続化
4. 外部API連携
【観点】
    - 外部連携の書き方
    - 例外処理書き方

:::note warn
もっというと、ローディングアニメーション付けたりマルチプラットフォーム対応させたり細かい実装あるのですが、
今回はあくまで、
「前提は理解した、あとは調べたら作れる」
まで持っていけたらと思います。
:::

まずは公式ドキュメントなどからflutterの概要をなんとなく理解し、
その後、flutter公式のGet Startedから始めて、それをベースに足りない部分を補うように学習を進めようと思います。

# 3. Flutterの仕組み
Flutterのドキュメントを見るにあたって以下の記事を参考にさせてもらいました。

https://qiita.com/fujit33/items/b16575d89946ffe187be

Flutterの仕組みを知る意図としては、Flutterでアプリを作る上での組み立て方を知ることを目的としています。

例えばUnityだとゲームオブジェクトというコンポーネントを作り、そこに機能を実装していきます。
ゲームオブジェクト同士の物理的干渉であったり、ユーザーイベントを考えながら処理を組んでいきます。

また、WebフレームワークでMVCで作られているフレームワークなどは、Controllerから作ってフロントとのエンドポイントをまず作ります。

Flutterはwidgetsと呼ばれるコンポーネントを組み合わせて、
レイアウトをを作成していく作りのようです。

公式の以下の図のように、様々なwidgetsを階層構造のようにしてレイアウトを組んで行き、
状態によってwidgetsの中身が変わるような、いわゆる宣言的UIという構築方法のようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662953/ccee9c49-1a92-fee2-37d6-14a469fbbbb2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662953/e144fad7-eba7-d20c-cae7-77e8cc756197.png)

https://docs.flutter.dev/ui/layout

公式も言ってますがReactに近い構造のようです。

>Flutter widgets are built using a modern framework that takes inspiration from React. 
> Flutter ウィジェットは、React からインスピレーションを得た最新のフレームワークを使用して構築されています。

https://docs.flutter.dev/ui

豊富なwidgetsをFlutterが提供してくれているのと、
有志で様々なレイアウトのサンプルが提供されているため爆速でレイアウトの構築とアプリ開発ができるようです。

Flutterを使用することのメリット、
他のネイティブアプリ開発プラットフォームと何が違うのか・なぜ人気なのかというのは以下の記事がわかりやすかったです。

https://qiita.com/yasutaka_ono/items/608405a27e57cc30e0d7
https://hackernoon.com/whats-revolutionary-about-flutter-946915b09514
https://qiita.com/teradonburi/items/913fb8c311b9f2bdb1dd

簡単にまとめると、
- 開発中のリアルタイムビルド・レンダリング（ホットリロード）が高速
- クロスプラットフォームでのJavaScriptブリッジの問題を解決している
    - ウィジェットとレンダラーをプラットフォームからアプリに取り込むことでOSへのアクセスを減らし高速化を実現している
- ライフサイクルもFlutter独自にラッピングされているため、Androidのライフサイクルと比べシンプル

上記の要素がFlutterの開発を高速にしており、
またネイティブアプリとして動かした時の速度としても利点があるということのようです。

# 3. ハンズオン
ある程度の仕組みや構造がわかったので、ハンズオンに入っていこうと思います。

ここは単純にFlutter公式のチュートリアルを進めていきます。

https://docs.flutter.dev/get-started/install

## 環境構築
選択肢を選んでいき、Mac OSでiOSアプリの開発を選択しました。
![スクリーンショット 2024-02-18 16.15.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662953/a93e2c00-8457-002b-842e-45dc7b173e5b.png)

指示に従ってSDKなどをインストールしていきます。

Flutterは以下のコマンドを実行することで環境構築の状況を確認できます。
```shell
$ flutter doctor
```
実は以前にflutterの環境構築(だけ)をしたことがあり、一通りインストールはされていたのですがFlutterのバージョンが古いようだだったので指示に従いバージョンアップを行いました。
その他もろもろエラーが出ましたが、先人の人たちの知恵(ググって)を借りて突破。

```shell
$ flutter doctor 

┌─────────────────────────────────────────────────────────┐
│ A new version of Flutter is available!                  │
│                                                         │
│ To update to the latest version, run "flutter upgrade". │
└─────────────────────────────────────────────────────────┘
Doctor summary (to see all details, run flutter doctor -v):

[!] Flutter (Channel stable, 3.10.2, on macOS 14.1 23B74 darwin-arm64, locale
    ja-JP)
    ! Warning: `dart` on your path resolves to
      /usr/local/Cellar/dart/2.17.6/libexec/bin/dart, which is not inside your
      current Flutter SDK checkout at /Users/{user_name}/Library/flutter.
      Consider adding /Users/{user_name}/Library/flutter/bin to the front of
      your path.
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
[✓] Xcode - develop for iOS and macOS (Xcode 15.2)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.2)
[✓] VS Code (version 1.85.0)
[✓] Connected device (2 available)
[✓] Network resources

! Doctor found issues in 1 category.
```

## チュートリアル

続いて、Test driveを実施していきます。
これをやればアプリ開発の始め方とホットリロードのやり方がわかるそうです。
今回、VSCodeを使用して開発を進めていこうと思います。

https://docs.flutter.dev/get-started/test-drive

新しくプロジェクトを作成すると初期のフォルダ構成としては以下のようになっています。
![スクリーンショット 2024-02-18 17.21.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662953/941cf46f-ca47-8a6c-fd7c-a517b9e1f877.png)

`android`や`ios`フォルダの中にはそれぞれのプラットフォームごとの設定ファイルや
拡張用のソースを書けるようになっているようです。
デフォルトでサンプルファイルが用意されており、中のコメントも充実しているので必要に沿って読んでいこうと思います。

まず、libフォルダ内のmain.dartというファイルが開きました。
中にはクラスやメソッドがデフォルトで複数あり、
コメントを読めばある程度何をする場所なのかわかりますが、こちらと並行して以下の動画を見ることで理解が進みました。
(画面遷移の方法も大体わかります。)

https://youtu.be/Cpg3otpYG9w?si=4EIXP3acMUGb0JxO


### ホットリロード
Flutterが人気の理由としてホットリロードがあり、
チュートリアルでもサンプルアプリ起動の次にホットリロードの説明が来ています。

ホットリロードとは
開発環境でアプリに何か変更を加えたときに
アプリを再起動したり状態を失わずに、ライブ実行中のアプリのコードをリロードする機能のようです。
確かに、アプリをエミュレーターで実行する場合必ずアプリ用にビルドをする必要があり、
Androidの開発をしていたときは、自動でやってはくれるもののビルドとアプリの再起動にかなり時間がかかっていました。

試しにチュートリアルにあるように文字の変更をして、command + s でSaveをしたら、
ものの1秒くらいで変更がアプリに反映される。。(めっちゃ早い)
かなり開発体験としていいですね。

## 初めてのFlutterアプリ

ここからは公式に誘導され、以下のチュートリアルを実施します。

https://codelabs.developers.google.com/codelabs/flutter-codelab-first?hl=ja#0

この記事は日本語なのと、1時間半くらいで実施できるようなのでサクッとやっていきましょう！

私は今回ターゲットデバイスをiOSで進めます。
また、2までは先ほどのチュートリアルで終わっているのでスキップして3の「プロジェクトを作成する」から初めていきます。

### プロジェクトを作成する

#### `pubspec.yaml`の編集
チュートリアルのバージョンが低いので単純にコピペではまずそうです。
バージョン表記が高いものはそのままにして、`dependencies`に以下のパッケージの依存関係の記載だけ追加しました。
(それ以外はデフォルトと一致していました。)
```yaml
english_words: ^4.0.0
provider: ^6.0.0
```

#### `analysis_options.yaml`の編集
これはコードの静的解析(linter)の設定のようです。
深く調べると時間が奪われそうなので、チュートリアルで設定するものだけ詳細を調べました。

```yaml
linter:
  rules:
    prefer_const_constructors: false # const推奨箇所でconstを付けるように推奨
    prefer_final_fields: false # 再利用されないフィールドをfinalにするように推奨
    use_key_in_widget_constructors: false # パブリック ウィジェットを作成するときにキーを提供できる機能を公開することを推奨
    prefer_const_literals_to_create_immutables: false # 不変クラスのインスタンス化でパラメータとして使用されるリスト、マップ、リテラルをインスタンス化するために const の使用を推奨
    prefer_const_constructors_in_immutables: false # @immutable クラスで const コンストラクターを宣言することを推奨
    avoid_print: false # print()を使用しないように推奨

```

この内容に関しては、開発の内容によって不要なものも出てきそうです。
おすすめのlinterの設定など調べたらありそうですね。
(今回は実務でないのでそこまで突っ込んで調べませんでした。)

#### `lib/main.dart`の編集
こちらに関しては素直に、チュートリアルの内容に置き換えます。
(上のlinterで引っかかっていた部分があったので、そこだけ解消しました。)

### ボタンを追加する ~ 新しいページを追加する
ここからはチュートリアルに従って淡々と進めていきます。

途中で「5分で終わるFlutter講座」というのがあり、`main.dart`の説明をしてくれています。
ここに関しては、最初の仕組みを調べたときに宣言的UIであることを知っていたので、
ある程度すぐに理解できました。

:::note info
Scaffoldについて
マテリアルデザイン用のベースクラスという理解。
`appBar`などが設定できて、画面のノッチなどに合わせていい感じにレイアウトしてくれるらしい。
https://api.flutter.dev/flutter/material/Scaffold-class.html
:::

# 4. まとめ

長くなってきたので、ここで一度区切ろうと思います。
ここまでのハンズオンで達成できたのは当初の目標の 1/4 くらいです。

チュートリアルでは細かい内容より、動くものを作ることにフォーカスされていました。
次回は既存のサンプルを利用して複雑なアプリのディレクトリ構成、ファイル分割の傾向、外部連携の方法を見ていこうと思います。