【Flutter入門】Flutterの周辺知識・セットアップ

# Flutterとは

`Flutter`は、マルチプラットフォーム開発手法の1つであり、プログラミング言語として`Dart`を採用している。
描画エンジンに`Skia`を搭載しており、ネイティブ並のレンダリング性能を誇る。

## 代表的なマルチプラットフォーム開発手法

- React Native
- Xamarin
- Progressive Web Apps(PWA)

# Flutterを採用するメリット

- 容易なモックアップ生成

> Material Designのウィジェットを描画する**Material Components**
> UIKitのウィジェットを描画する**Cupertino**

- ホットリロードの採用

> デバッグ時はDartの`Just-In-Time(JIT)コンパイラ`を採用
> → クラス・メソッド単位での逐次実行
> 
> リリース時はDartの`Ahead-Of-Time(AOT)コンパイラ`を採用
> → 事前コンパイルによる高速な動作

- Dartの柔軟性

> 静的型付け・動的型付けの両方での宣言が可能

## 静的型付け言語 vs. 動的型付け言語

|  | 静的型付け言語 | 動的型付け言語  |
| --- | --- | --- |
| 文法エラー | コンパイル時 | 実行時 |
| 記述量 | 多い | 少ない |
| 実行速度 | 速い | 遅い |
| 保守性 | 良い | コードの肥大化とともに悪化 |

# Flutterを採用するデメリット

- 日本語の入出力に関するバグが存在

> フォント相性による不自然な文字列配置、Android端末の特定IMEでのキー入力の不具合
> → ネイティブ連携技術による回避が可能

***

# Flutterの環境構築(macOS)

[Flutter | macOS install](https://flutter.dev/docs/get-started/install/macos)

## Homebrew経由でのFlutterのインストール

```shell
$ brew install --cask flutter
```

## インストールの確認

[`flutter doctor --android-licenses`の実行時に`NoClassDefFoundError`が発生した場合](https://zenn.dev/captain_blue/articles/flutter-android-licenses-classnotfound)

```shell
$ flutter doctor                   
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.2.3, on macOS 11.5.2 20G95 darwin-x64, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.2)
[✓] VS Code (version 1.59.0)
[✓] Connected device (1 available)

• No issues found!
```

### 詳細情報を閲覧する場合

```shell
% flutter doctor -v
[✓] Flutter (Channel stable, 2.2.3, on macOS 11.5.2 20G95 darwin-x64, locale ja-JP)
    • Flutter version 2.2.3 at /usr/local/Caskroom/flutter/2.2.3/flutter
    • Framework revision f4abaa0735 (8 weeks ago), 2021-07-01 12:46:11 -0700
    • Engine revision 241c87ad80
    • Dart version 2.13.4

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Users/b150005/Library/Android/sdk
    • Platform android-30, build-tools 30.0.3
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.5.1, Build version 12E507
    • CocoaPods version 1.10.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)

[✓] VS Code (version 1.59.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (1 available)
    • Chrome (web) • chrome • web-javascript • Google Chrome 92.0.4515.159

• No issues found!
```

## IDE(統合開発環境)

iOSアプリを開発する場合は**Xcode**、Androidアプリを開発する場合は**Android Studio**、その他アプリを開発する場合は**Visual Studio Code**が利用可能。

***

# Flutterプロジェクト構造

|  |  |  |  |  | 説明 |
| --- | --- | --- | --- | --- | --- |
| android | app | build.gradle |  |  | アプリケーションのビルド設定 |
| ^ | ^ | src | debug |  | デバッグビルド用の設定(Android) |
| ^ | ^ | ^ | main | AndroidManifest.xml | Androidの設定 |
| ^ | ^ | ^ | ^ | java | プラグインなどで利用するJavaコード |
| ^ | ^ | ^ | ^ | kotlin | Androidのネイティブ実装 |
| ^ | ^ | ^ | ^ | res | 文字列・アイコンなどのリソースファイル |
| ^ | ^ | ^ | profile |  | プロフィールビルド用の設定 |
| ^ | build.gradle |  |  |  | 全てのモジュールの依存関係 |
| build |  |  |  |  | ビルド済みのファイル |
| ios | Flutter | Debug.xcconfig |  |  | デバッグビルド用の設定(iOS) |
| ^ | ^ | Release.xcconfig |  |  | リリースビルド時の設定 |
| ^ | Runner | AppDelegate.swift |  |  | iOSのネイティブ実装 |
| ^ | ^ | Assets.xcassets | AppIcon.appiconset |  | アイコン |
| ^ | ^ | ^ | LaunchImage.imageset |  | スプラッシュ画像 |
| ^ | ^ | Base.lproj | LaunchScreen.storyboard |  | スプラッシュ |
| ^ | ^ | ^ | Main.storyboard |  | iOSのストーリーボード |
| ^ | ^ | Info.plist |  |  | アプリケーションの設定ファイル |
| lib |  |  |  |  | Flutterのコード |
| ^ | main.dart |  |  |  | Flutterで最初に実行されるコード |
| pubspec.yaml |  |  |  |  | ライブラリのバージョン, Flutter/Dartのパッケージ情報 |
| test |  |  |  |  | 自動テスト |
| web |  |  |  |  | Flutter Web用の設定 |

# Linterの設定

[Flutter | Introducing package:flutter_lints](https://flutter.dev/docs/release/breaking-changes/flutter-lints-package)

Flutterプロジェクト作成時点では、DartのLinterが`External Libraries/Dart Packages/flutter/src/analysis_options_user.yaml`で設定されているが、
このLinterはFlutterプロジェクトに最適化されていないため、Flutterの推奨Linterである`flutter_lints`を導入する。

① ターミナルでFlutterプロジェクトのルートディレクトリに移動

```shell:ターミナル
$ cd #Flutterプロジェクトのルートディレクトリ
```

② 以下のシェルスクリプトを実行し、`pubspec.yaml`ファイルに利用するLinter情報を追記
→ `dev_dependencies`に`flutter_lints: ^1.0.4`が自動で追記される
※ `pubspec.yaml`はプロジェクトの設定情報・パッケージ管理を行うファイル。([参考: 【Flutter】プロジェクトの環境設定はpubspec.yaml](https://dtpscriptin.com/flutter-pubspec-yaml/))

```shell:ターミナル
$ flutter pub add --dev flutter_lints
Resolving dependencies...
  async 2.6.1 (2.8.2 available)
  charcode 1.2.0 (1.3.1 available)
+ flutter_lints 1.0.4
+ lints 1.0.1
  matcher 0.12.10 (0.12.11 available)
  meta 1.3.0 (1.7.0 available)
  test_api 0.3.0 (0.4.3 available)
Downloading flutter_lints 1.0.4...
Downloading lints 1.0.1...
Changed 2 dependencies!
```

③ `analysis_options.yaml`ファイルを**Flutterプロジェクトのルートディレクトリ**に作成

④ 生成した`analysis_options.yaml`ファイルに以下の文言を記載

```yaml:analysis_options.yaml
include: package:flutter_lints/flutter.yaml
```

⑤ ターミナルからFlutterプロジェクトに対して`flutter_lints`を適合
→ 実行結果からも分かるように、`flutter pub get`でもインストールが可能

```shell:ターミナル
$ flutter analyze
Running "flutter pub get" in app...                                414ms
Analyzing app...                                                        

   info • Use key in widget constructors • lib/main.dart:7:7 • use_key_in_widget_constructors
   info • Prefer declaring const constructors on `@immutable` classes • lib/main.dart:31:3 •
          prefer_const_constructors_in_immutables
   info • Prefer const with constant constructors • lib/main.dart:96:13 • prefer_const_constructors
   info • Prefer const with constant constructors • lib/main.dart:109:16 • prefer_const_constructors

4 issues found. (ran in 1.0s)
```

⑥ ターミナルから現時点での`flutter_lints`による指摘箇所をリファクタリング

```shell:ターミナル
$ dart fix --apply
  ╔════════════════════════════════════════════════════════════════════════════╗
  ║ The Dart tool uses Google Analytics to report feature usage statistics     ║
  ║ and to send basic crash reports. This data is used to help improve the     ║
  ║ Dart platform and tools over time.                                         ║
  ║                                                                            ║
  ║ To disable reporting of analytics, run:                                    ║
  ║                                                                            ║
  ║   dart --disable-analytics                                                 ║
  ║                                                                            ║
  ╚════════════════════════════════════════════════════════════════════════════╝

Computing fixes in app...      8.6s
Applying fixes...                      0.0s

lib/main.dart
  prefer_const_constructors_in_immutables • 1 fix

1 fix made in 1 file.
```

***

# 外部ライブラリの追加

[参考: Package dependencies](https://dart.dev/tools/pub/dependencies)
[参考: Dart packages(pub.dev)](https://pub.dev/)

Flutterプロジェクトに依存関係を追加する手順は、以下の通り。

① `pubspec.yaml`ファイルの`dependencies:`セクションに利用する**ライブラリ**と**バージョン**を追記
→ 現時点での最新バージョンが不明な場合は、ターミナルで`flutter pub add --dev <外部ライブラリ>`コマンドを実行し、
  `dev_dependencies:`要素からカット&ペーストで持ってくることも可能。

```yaml:pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  english_words: ^4.0.0   # 利用したい外部ライブラリ
```

② ターミナルで`flutter pub get`コマンドを実行し、ライブラリをインストール
→ Android Studioでは、**Pub get**ボタンをクリックすることでコマンドを実行できる。

```shell:ターミナル
$ flutter pub get
Running "flutter pub get" in app...                                399ms
Process finished with exit code 0
```