Flutterことはじめ

# はじめるには

1. SDK/binふくむリポジトリをcloneする
2. 環境変数のexport
3. `$flutter doctor` を実行して必要な設定をしていく
4. VSCodeに拡張機能を入れる

これだけでサンプルを動かすところまでいけます。
詳しくは[他の方の記事](https://qiita.com/ryosomiya/items/9502bdcba202dae1d876)を参考に。

私の環境だとiOS/Androidは両方開発しているマシンなのですが以下の警告が

```sh
HanedaKentarou-no-MacBook-Pro.local ^_^  ~/Documents/workspace/flutter
% flutter doctor                                                      [19:26:38]
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, v1.0.0, on Mac OS X 10.13.6 17G65, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
[!] iOS toolchain - develop for iOS devices (Xcode 9.4.1)
    ✗ ideviceinstaller is not installed; this is used to discover connected iOS
      devices.
      To install with Brew, run:
        brew install --HEAD usbmuxd
        brew link usbmuxd
        brew install --HEAD libimobiledevice
        brew install ideviceinstaller
    ✗ ios-deploy not installed. To install with Brew:
        brew install ios-deploy
[✓] Android Studio (version 3.1)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[!] VS Code (version 1.30.1)
[!] Connected device
    ! No devices available
```

指定されるがままにbrewでパッケージインストールを実行して、Android Studio立ち上げてFlutter/Dartのプラグインをinstallしました。

> open -a Simulator.app

でiOSのエミュレーターが立ち上がるのであとはサンプルを実行できます。

# 利用できるサンプル

```
HanedaKentarou-no-MacBook-Pro.local ^_^  ~/Documents/workspace/flutter/flutter (beta)
% tree -L 2                                                           [19:46:13]
.
├── AUTHORS
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── PATENTS
├── README.md
├── analysis_options.yaml
├── bin
├── dartdoc_options.yaml
├── dev
├── examples // ここにいっぱいある
│   ├── README.md
│   ├── catalog
│   ├── flutter_gallery
│   ├── flutter_view
│   ├── hello_world
│   ├── layers
│   ├── platform_channel
│   ├── platform_channel_swift
│   ├── platform_view
│   └── stocks
├── flutter_console.bat
├── packages
└── version
``` 

#### Hello World Exampleがコケる

```
HanedaKentarou-no-MacBook-Pro.local ^_^  ~/Documents/workspace/flutter/flutter/examples/hello_world (beta)
% flutter run                                                         [19:44:42]
Launching lib/main.dart on iPhone X in debug mode...
Starting Xcode build...
 ├─Assembling Flutter resources...                    1.2s

 └─Compiling, linking and signing...                  2.7s

Xcode build done.                                            5.1s
 3.8s
ProcessException: Process "/usr/bin/xcrun" exited abnormally:
"io.flutter.examples.hello-world": -1

An error was encountered processing the command
(domain=FBSOpenApplicationServiceErrorDomain, code=1):
The request to open ""io.flutter.examples.hello-world"" failed.
The request was denied by service delegate (SBMainWorkspace) for reason: NotFound
("Application ""io.flutter.examples.hello-world"" is unknown to FrontBoard").
Underlying error (domain=FBSOpenApplicationErrorDomain, code=4):
	The operation couldn’t be completed. Application
	""io.flutter.examples.hello-world"" is unknown to FrontBoard.
	Application ""io.flutter.examples.hello-world"" is unknown to FrontBoard.
  Command: /usr/bin/xcrun simctl launch 7564F011-A817-4AEE-BDDB-2BB57D4DF411
  "io.flutter.examples.hello-world" --enable-dart-profiling --enable-checked-mode
  --observatory-port=0
Error launching application on iPhone X.
```

issueが上がっており、直接plistを編集すれば治せるらしいが無視。
アプリケーションのビルドとインストールには成功しているので直接起動はできる。

### その他サンプル

各種READMEがあるが、**結構動かないのが多い。**
まぁデフォルトブランチがまだ **Beta** なのでご愛嬌。

とりあえず `examples/flutter_gallery` が全体像を見るにはいい感じ。

取りあえず動くのを確認してUIのセットと実装をこれで確認した。

# 完全に理解した（してない）

### 理解のための記事

- [5分で入門するFlutter](https://speakerdeck.com/natumn/5fen-deru-men-suruflutter?slide=20)
- [仕組みを知れば怖くない！ Flutter入門](https://speakerdeck.com/najeira/shi-zu-miwozhi-rebabu-kunai-flutterru-men?slide=23)
- [Flutterでstaging/production環境の切替](http://kirimin.hatenablog.com/entry/2018/04/21/220303)
- [DART/FLUTTER 入門 + 最強の勤怠アプリを作った話](https://adwd.github.io/dart-flutter-slide/#/)
- [konifar/droidkaigi2018-flutter](https://github.com/konifar/droidkaigi2018-flutter)
- [FlutterでCI環境作ろうとしたけど諦めた話](https://note.mu/shogoyamada/n/n014c59951c8d)

### 理解したこと

- Widgetの組み合わせでUIもソースで定義する
- Hot Reloadあり、VSCodeで開発できて便利
    - これがあるのでStoryboard/LayoutFile的なのがなくても困らなそう
- 基本的にMaterialDesign準拠
- Swift/Kotlinと繋げられる
- Webベースだと思ってたけどぜんぜん違う、レイアウトはDom✖、オリジナルのWidget構造をレンダリングしている
- [CookBook](https://flutter.io/docs/cookbook)がめちゃ便利
- 環境ごとの設定（dev/stg/prod）などは基本的にこれまでの各platformの設定と同じ（ios:Build Scheme, Android:Buiuld Flavor）
- 実機、エミュレーターのビルド・デバッグもVSCodeからいけそう
- Dart
    - JSに変換できるのでWebでも動く
    - async/await/class/optional/genericsは動く
- React/Flux理解あるといい感じのコンポーネント
- Animation周りがそこまで直感的じゃない
- まだassetとしてsvgやvectorは使えなそう
    - [Support a vector drawable format #1831](https://github.com/flutter/flutter/issues/1831)
- 無料枠だとCI系サービスは厳しそう

### Dart

- [公式Dartチュートリアル](https://www.dartlang.org/tutorials)
    - [Dart Playground](https://dartpad.dartlang.org/)で書いてみる
  

```Dart
void main() {
  for (int i = 0; i < 5; i++) {
    print('hello ${i + 1}');
  }
}

class Car{
  //// 変数宣言
  var name = 'my-car';
  // 明記的に動型付
  dynamic name1 = 'my-car';    
  // 型明記
  String name2 = 'my-car';
  // 初期化無視、default = null
  var name3;
	// const v1 = 0; // エラーになる
  final v2 = 0;

  
  //// functions
  // []で囲むと省略可能
  bool isEnable(int arg, [int optionalArg]){
    return true;
  }
  // {}で囲むとデフォルト値指定しつつ、コール時にlabelをつけられる
  bool isEnable2({bool arg = false}){
    return true;
  }
  // @requiredはドキュメントにあるけどplaygroundだとエラー出る
	// bool isEnableShort({int arg, @required String requiredName, String noRequiredName}) => arg == 0;
  // 省略
  String playerName(String name) => name ?? 'Guest';
  
  void cascade1() => {};
  void cascade2() => {};
  
  // static method
  static staticMethod() => {};
  
  // getter / setter
  num get getterSetterVal1 => v2 + 1;
  set getterSetterVal1(num value) => v2;
  
  // constructor
  Car(String arg){
    this.name = arg;
  }

  void run(){
    // imutable指定
    const v1 = 0;
    final v2 = 0;
    
    // 配列
    var arr = [1];
    // 長さ
    print(arr.length);
    // for each
    arr.forEach((element){
      print(element);
    });
    // 省略形
    arr.forEach((element) => print(element));

    // sring -> int
    var one = int.parse('1');
    // 文字列展開
    print('hello ${one + 1}');
    // map
    var mapArr = {
      'v1': 1, 'v2': 2
    };
    // 値変更
    mapArr['v1'] = 10;
    // map型指定初期化
    var mapArr2 = Map<int, String>();
    
    var isEnableRun = this.isEnable(0);
    var isEnableRun2 = this.isEnable(0);
    
    double dbVar = 1.0;
    int intVar = 1;
    // castしなくてもいける
    var sum = dbVar + intVar;
    
    // cascadeによる省略
    var car = Car("sample");
    car
      ..cascade1()
      ..cascade2();

    // 例外
    try{
      
    }on Exception catch (e) {
      // Anything else that is an exception
      print('Unknown exception: $e');
    } catch (e) {
      // No specified type, handles all
      print('Something really unknown: $e');
    } finally {
      
    }
    
    // 型取得
    print('The type of a is ${sum.runtimeType}');
    
    
  }
}

// mixin
mixin SampleMixin{
  bool val = true;
}
class Mixined with SampleMixin{
}

// 癖がなく特に気にならないもの
// while, for, switch, assert, async await, abstract, implement, extend, generics, comment

// とりあえず理解したもの
// Factory Constructor, import libs, await for
```


  
issueのコメントが盛り上がっているところを見るとまだやはりネイティブで共通だけど困りがちなassetの管理とビルド設定の管理系はまだそれぞれのプラットフォームの仕組みを使う感じで抽象化はできてなさそうだ。

cordova/titanium/ruby motion/Xamarin/React Nativeときてそろそろ覇権をとってほしいので頑張ってほしい。
メリークリスマス。 :santa: