Flutter 1.0がリリースされたので概要から、環境構築、実装方法、アーキテクチャ、情報収集方法まで全部書く

この記事は[Flutterアドベントカレンダー 13日目](https://qiita.com/advent-calendar/2018/flutter)の記事です。

2018/12/5に行われた、[Flutter Live](https://developers.google.com/events/flutter-live/) でFlutter バージョン1.0がリリースされ安定板となりました。

![スクリーンショット 2018-12-11 9.56.04.png](https://qiita-image-store.s3.amazonaws.com/0/139360/c8b782ba-9a4c-197c-23a8-905a785e6094.png)


これを記念して、Flutterのことをできるだけたくさん書きたいと思います。


## Flutter 概要

### 概要

Flutterのページにはデカデカと下記の一文が書かれています。

![スクリーンショット 2018-12-12 12.39.43.png](https://qiita-image-store.s3.amazonaws.com/0/139360/c3a418fd-9c47-767b-ee95-e55662225eec.png)


**Flutter allows you to build beautiful native apps on iOS and Android from a single codebase.**

> Flutterを使えば、１つのコードで美しいネイティブiOSとAndroidアプリを構築できる

他にも下記の３点を掲げています。

- Fast Development (素早い開発)
- Expressive and Flexible UI(表現豊かで、フレキシブルなUI)
- Native Performance(ネイティブパフォーマンス)


<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">v2.3.2をリリースしました！<br><br>・トップ画面のリニューアル<br>・写真一覧画面のリニューアル<br>・ダークテーマに切り替えてられる機能の追加<br><br>iOS <a href="https://t.co/P9yfLxfElX">https://t.co/P9yfLxfElX</a><br><br>Android <a href="https://t.co/sYdG9cAPOr">https://t.co/sYdG9cAPOr</a> <a href="https://t.co/Vym5biSGcs">pic.twitter.com/Vym5biSGcs</a></p>&mdash; shogo.yamada@Flutterマン (@yshogo87) <a href="https://twitter.com/yshogo87/status/1056082185067753473?ref_src=twsrc%5Etfw">2018年10月27日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


上記のツイートをご覧ください。この動画は自分が開発したアプリです。ネイティブと同じパフォーマンスで動いているのがわかると思います。


### 技術的な話

Flutterは自分自身でレイアウトを生成するロジックを持っていて、iOSの場合は `FlutterViewController` で Androidの場合は　`MainActivity` の上でレイアウトを生成します。

詳しくは下記の記事をご覧ください。細かくどうやって動いているのか、がかかれています。

https://flutter.io/docs/resources/technical-overview


### 全てはWidget

Flutterではレイアウトの全ては `Widget` です。
基本的に全てWidgetを組み合わせることで実装します。

https://flutter.io/docs/development/ui/widgets

![DpYUDjvU8AExNE8.jpg](https://qiita-image-store.s3.amazonaws.com/0/139360/efb98432-1020-f633-9e72-c7c74f873769.jpeg)


### 言語

言語は **Dart** を使って実装していきます。

下記のコードは画面の中央に Hello World と表示するコードです。

```dart

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
          primaryColor: Colors.white
      ),
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("ホーム"),
      ),
      body: new Center(
        child: Text("Hello World"),
      ),
    );
  }
}
```

なぜFlutterがDartを選択したのか。みたいな話は下の記事の中で言及されています。

https://hackernoon.com/why-flutter-uses-dart-dd635a054ebf

少し長いですが、興味のある方は上記の記事をご覧ください。

概要を説明すると基本的に下記の3点の理由です。

- ホットリロードを実現するため
- ガーベジコレクションがある
- JavaとJavaScriptの中間的な言語だから

## アーキテクチャについて

Flutterではレイアウトも、ロジック全てDartで書くので、全てが混在してしまってテストが書きづらくなってしまう可能性があるので、アーキテクチャは何かしら学習するのがいいと思います。

そこでGoogleが提唱しているアーキテクチャはBLoCです。
下記の動画で紹介されています。

https://www.youtube.com/watch?v=RS36gBEp8OI&t=453s

https://www.youtube.com/watch?v=PLHln7wHgPE&t=37s

BLoCには下記の４つのルールがあります。

- BLoCの入力・出力インターフェースはすべてStream/Sinkである
- BLoCの依存は必ず注入可能で、環境に依存しない
- BLoC内に環境ごとの条件分岐は持たない
- 以上のルールに従う限り実装は自由である

詳しい実装方法は下記の記事をご覧ください

- https://www.shogogeek.com/entry/2018/09/13/073303

他にもいろいろなアーキテクチャが考えられているようで下記のリポジトリにいろんなアーキテクチャのサンプルコードがあります。詳しくはこちらをご覧ください。

https://github.com/brianegan/flutter_architecture_samples

## 学習方法

これからFlutterをやりたい！でもどうやって勉強していけばいいかわからない。という方がいらっしゃるとおもいます。
そこでおすすめなのはGoogleが出しているCodelabsをやるのがとてもいいと思います。

<img width="788" alt="スクリーンショット 2018-12-11 12.27.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/139360/a0172f38-2049-c1f4-7d9b-9da2c5dcd97a.png">


https://flutter.io/docs/codelabs

ここではHello Worldだせた後の、初歩的なところからFirebaseと一緒に使う方法までしっかり勉強できるような内容になっているのでかなりおすすめです。

他にもYouTubeにもいろんなチュートリアルをあげている方もたくさんいらっしゃるのでその辺をみるのもいいでしょう。

https://www.youtube.com/watch?v=GLSG_Wh_YWc&t=1s

自分はCodelabsをやった後、Twitterのレイアウトを真似して作りました。

https://note.mu/shogoyamada/n/n0d29a5b16e8c

Codelabやった後はお好きなアプリのレイアウトを真似するのもいいと思います。


## 環境構築方法

環境構築方法としては詳しくは説明しません。詳しくは下記の手順にしたがって開発環境を作りましょう。

https://flutter.io/docs/get-started/install/macos

主な流れとして

- SDKをダウンロードする
- パスを通してflutterコマンドが打てるようにする
- XcodeとAndroid　StudioをダウンロードをしてiOSとAndroidの開発環境を整える
- VSCodeで開発する人はそれ用のプラグインを、Android Studioで開発する人はそれ用のプラグインを導入する


## レイアウトの組み方のコツ

レイアウトの組み方は色々な手段がありますが、ベースとして **Row(横並び)とColumn(縦並び)を組み合わせていく** ということを知っておくといいでしょう。

![device-2018-12-12-115221.png](https://qiita-image-store.s3.amazonaws.com/0/139360/b6fb7870-6a73-be40-2a86-1147770b7bee.png)

(図がわかりにくくてすいません😭)

```dart
Column(
   children: <Widget>[
     // 縦並びのWidgetを配置
     Row(
       children: <Widget>[
          // 横並びのWidgetを配置
       ],
    )
   ],
),
```

## Flutterでできること

クロスプラットフォームでよくある、「〜〜〜できない」みたいな話はよくあると思います。例えば「PWAだったらPush通知を受信できない」とか「デザインガイドラインに従ったレイアウトは組めない」とかあると思いますが、Flutterでは基本的にこの辺りは解決されています。

### Push通知

Push通知はFirebase Messageingのプラグインで実現できます。

<img width="1024" alt="スクリーンショット 2018-12-11 11.52.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/139360/68a2b196-d2bb-cf65-3e57-b0ce97997dd0.png">

https://pub.dartlang.org/packages/firebase_messaging

こちらのツイートの動画は実際にPush通知を受け取っている様子です。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">明日のFlutter meetupで使う動画。<br>Flutterでチャット機能結構できてきたぞ！！ <a href="https://t.co/L2QRoQnVXN">pic.twitter.com/L2QRoQnVXN</a></p>&mdash; shogo.yamada@Flutterマン (@yshogo87) <a href="https://twitter.com/yshogo87/status/1070249502118801408?ref_src=twsrc%5Etfw">2018年12月5日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

### デザインについて

自分がFlutterを始めた半年前はマテリアルデザインのWidgetばかり、iOSのWidgetは用意されていませんでした。
ですが、今ではiOSのWidgetもちゃんとサポートされています。

<img width="971" alt="スクリーンショット 2018-12-11 12.19.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/139360/9ad109e2-734b-c0f1-3ec9-ddf1b5a0dfd9.png">

https://flutter.io/docs/development/ui/widgets/cupertino

もちろんマテリアルデザインもサポートされています。

<img width="955" alt="スクリーンショット 2018-12-11 12.21.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/139360/1f855905-1291-f1fb-067d-f7b49efc3994.png">

https://flutter.io/docs/development/ui/widgets/material

また、iOSとAndroidで分岐するメソッドも用意されているので、プラットフォームごとに別のレイアウトを実装することもできます。

```dart

if (Platform.isIOS) {
// iOSのときだけの処理

} else if (Platform.isAndroid) {
// Androidだけの処理
}
```

## テストについて

Flutterではテストについてもサポートされています。

![スクリーンショット 2018-12-12 12.12.14.png](https://qiita-image-store.s3.amazonaws.com/0/139360/d79d9c51-2adb-aef3-a0da-ad8b1a5ce855.png)

https://flutter.io/docs/testing

テスト方法についても `Unit Test` と `Widget Test` がちゃんと標準でサポートされているので、普通のネイティブアプリの同じ水準でテストがかけるでしょう。

自分のプロジェクトで書いているユニットテストを例にあげておきます。

```dart
void main() {
  GroupDetailHelper helper;
  setUp(() async {
    helper = GroupDetailHelper();
  });

  test("isDeletePhoto 削除できないユーザー 引数がと一致しない", () {
    expect(helper.isDeletePhoto("1", "2"), equals(false));
  });

  test("isDeletePhoto 削除できないユーザー 引数がnull", () {
    expect(helper.isDeletePhoto("2", "2"), equals(true));
  });
}

```

## CI/CDについて

FlutterのCI/CDについても問題なく回せます。

CIについては下記の記事をご覧ください。

https://medium.com/flutter-community/setup-ci-cd-pipeline-for-your-flutter-app-using-circleci-ef07e39982ab

CDについては公式ページに記載があります。

![スクリーンショット 2018-12-12 12.17.21.png](https://qiita-image-store.s3.amazonaws.com/0/139360/97445220-6c8a-089b-88fc-76054cac3d21.png)

https://flutter.io/docs/deployment/fastlane-cd

## Flutterで実装に困った時

Flutterだけではできないことがあったり、プラットフォーム独特の実装の場合は、プラグイン(Flutterのライブラリのようなもの)を探してみましょう。

<img width="1008" alt="スクリーンショット 2018-12-11 12.26.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/139360/2c576938-ce7d-b62e-85a3-2321bd81c15c.png">


https://pub.dartlang.org/

ここにもなくてどうしてもやりたいことがある場合は、メソッドチャンネル経由でネイティブの実装を書いてFlutterから呼ぶことを検討しましょう。

https://flutter.io/docs/development/platform-integration/platform-channels

## Firebaseとの相性

最近のモバイル開発ではFirebaseと一緒に使うことが主流になってきていると思います。Firebaseを使えばモバイルに必要な機能はだいたい揃っているので、ぜひ使いたいところだと思います。

FlutterではFirebase用のプラグインが公開されていて基本的には、Firebaseの機能は全部使えます。

<img width="902" alt="スクリーンショット 2018-12-11 12.31.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/139360/b6c27eaf-f38c-b6a1-04eb-b0f019cbeb5b.png">

https://github.com/flutter/plugins/blob/master/FlutterFire.md

一部、MLKitの on Cloudがサポートされていなかったりしますが、主要なものは基本的に使えます。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Flutterで画像を複数選択できるプラグインがあったので使ってみた！<br>これでSwiftとKotlinコードを削除して、全部Dartでいけるぞ！！<br><br>実装方法については明日のアドベンドカレンダーで公開します😋😋 <a href="https://t.co/l22P0Yhj9B">pic.twitter.com/l22P0Yhj9B</a></p>&mdash; shogo.yamada@Flutterマン (@yshogo87) <a href="https://twitter.com/yshogo87/status/1069577762829025282?ref_src=twsrc%5Etfw">2018年12月3日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

こちらのツイートで紹介されている動画のアプリも基本的にFirebaseのサービスを使って実装しています。

- Firebase Storage
- Cloud Firestore
- Firebase Messaging

MLKitをFlutterから使ってみた記事も書きました。

https://note.mu/shogoyamada/n/n4130f99c787e

## 情報収集方法

最後に情報収集方法です。
ここでは自分が実際にやっていることを書きますので、他にこんな方法もあるよ！！みたいなアドバイスがあればコメント欄や、Twitterで教えてください。

### Twitterアカウントのフォロー

下記のアカウントをフォローしておくと、いい記事が流れてくるのでおすすめです。

https://twitter.com/r_flutterdev


### Feedly でFlutter関連を追う

自分は毎朝ここからFlutter関連の記事をみています。

https://feedly.com

### Flutter weeklyに登録する

Flutter Weeklyに登録すると、Flutterの良さそうな記事を毎週まとめてメールで送ってくれます。

https://flutterweekly.net/

## Flutter Liveで発表されたこと

- Flutter 1.0の発表
- Squareという決済SDKのサポート
- Flareというコードを書かなくてもアニメーションつくれる
- Codemagicという新しいCI/CD
- HummingBirdというFlutterをWebで動かせるSDKの発表

発表の中で今一番注目されているHummingBirdというWebでFlutterを動かせるということだと思います。

https://medium.com/flutter-io/hummingbird-building-flutter-for-the-web-e687c2a023a8


## これからのFlutterの動き

これからFlutterはどんどん発展していくとは思います。
現時点で変わっていること下記です。

- デスクトップでそのまま動く（https://github.com/google/flutter-desktop-embedding)
- WEBでもそのまま動く(HummingBird)
- Add to App(ネイティブのViewをそのままFlutter上に表示できる)

これからGoogleが開発している新しいOSとして、Fuchsiaの開発も進めていて、Flutterで実装しているらしいので、これからのFlutterの動向が楽しみです。

- [Androidがなくなるのは時間の問題かもしれない。](https://note.mu/shogoyamada/n/ne573d99905f5)