Flutter 再入門

一昔前にFlutterを触っていたものの、最近はほとんど触る機会がなくなってしまったので、おさらいを兼ねて
この方の記事を参考にして、効率的にキャッチアップしていく。- 公式ドキュメントを読む:https://flutter.dev/docs
- Udacity online Flutter Training:https://www.udacity.com/course/build-native-mobile-apps-with-flutter--ud905
- Udemy:https://www.udemy.com/course/flutter-bootcamp-with-dart/
- レイアウトを体系的に学ぶ:https://medium.com/flutter-community/flutter-layout-cheat-sheet-5363348d037e
- 状態管理手法について学ぶ:
- setState()
- Scoped Model
- provider + ChangeNotifier パターン
- BLoC パターン
- どれを使うべきか迷ったらフローチャート:https://twitter.com/_mono/status/1170516947970097152?s=20
の順に勉強してくと良さげ。
その他
- Cookbook:https://flutter.io/cookbook/
- flutter/samples:https://github.com/flutter/samples
- アニメーション:https://speakerdeck.com/konifar/flutter-animations-first-step
記事中では、上記以外にもいろいろ情報をまとめて下さっているが、消化しきれないのでこの辺にしておいて、とりあえずやっていく。

公式ドキュメントを読んでいく
インストール
普段はMacを使っているのでこちらを見ながらインストールしていく。
M1 Mac を使う場合は以下に留意したほうがよい。

Android setup
これまで Android Studio 使ったことはなかったが、今回はちゃんとセットアップしてみる。
Android Studio をインストールしたあと flutter doctor
したら Android license status unknown
のエラーが出た。
> flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.2.0, on macOS 11.4 20F71 darwin-x64, locale ja-JP)
[!] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.2)
[✓] VS Code (version 1.58.2)
[✓] Connected device (1 available)
! Doctor found issues in 1 category.
flutter doctor --android-licenses
すれば良いということで実行したが、またしてもエラー。
> flutter doctor --android-licenses
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
at com.android.repository.api.SchemaModule$SchemaModuleVersion.<init>(SchemaModule.java:156)
at com.android.repository.api.SchemaModule.<init>(SchemaModule.java:75)
at com.android.sdklib.repository.AndroidSdkHandler.<clinit>(AndroidSdkHandler.java:81)
at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:73)
at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:48)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.XmlSchema
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 5 more
どうやら Android SDK Command-line Tools
が入っていないことが原因。
2.Start Android Studio, and go through the ‘Android Studio Setup Wizard’. This installs the latest Android SDK, Android SDK Command-line Tools, and Android SDK Build-Tools, which are required by Flutter when developing for Android.
と書かれているが、2021/7/23 時点、Android Studio のセットアップウィザードで Standard
を選択してインストールした限りでは Android SDK Command-line Tools
はインストールされない。おそらく Custom
セットアップする必要があるんだと思う。
に従ってインストールことで解決。
> flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.2.0, on macOS 11.4 20F71 darwin-x64, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.2)
[✓] VS Code (version 1.58.2)
[✓] Connected device (1 available)
• No issues found!

macOS setup
以前はなかった desktop 用のセットアップも行う。
- Xcode
- CocoaPods
は既に入っているので flutter config --enable-macos-desktop
を実行するだけ。
> flutter config --enable-macos-desktop
Setting "enable-macos-desktop" value to "true".
You may need to restart any open editors for them to read new settings.
特に問題なく完了。flutter devices
で確認すると、macOS を認識するようになった。
> flutter devices
3 connected devices:
sdk gphone x86 (mobile) • emulator-5554 • android-x86 • Android 11 (API 30) (emulator)
macOS (desktop) • macos • darwin-x64 • macOS 11.4 20F71 darwin-x64
Chrome (web) • chrome • web-javascript • Google Chrome 92.0.4515.107
Desktop support についてはこちらのページが詳しい。
Desktop | channel |
---|---|
Windows (Win32) | stable |
macOS | stable |
Linux | stable |
Windows UWP | dev |
- Desktop support はまだ
beta
リリース- アクセシビリティサポートなど、フィーチャーギャップがある状態
- だけど
stable
channel で試すことができる。- Desktop support を簡単に試せるように、stable channel に desktop の beta snapshot を出荷しているとのこと。
- ただし、beta snapshot は次の stable release までは更新されないので、最新バージョン使用したければ beta channel に切り替えないといけない。
- UWP support は
alpha
リリース。-
dev
channel で試すことができる。
-
他にもDesktop用の情報がいろいろ載っているので、また後で戻ってこよう。

Set up an editor
Flutter を開発するにはどのエディターを使ってもよいが、Flutter公式には以下のエディター用プラグインを用意しているので、いずれかを使うのがお勧め。
- Android Studio/IntelliJ IDEA
- Visual Studio Code
- Emacs
普段 VSCode 使っていて、既に Flutter 用の extension も入っているので、今回は新たに IntelliJ IDEA を入れてみた。
Test Drive
macOS にして実行してみた。Hot reload も問題なく動作していていい感じ。

Write your first Flutter app
以前にもやっているのでスキップするが、やることを列挙しておく。
- Part1
- MaterialApp の scafford
- 外部ライブラリのインストール
- Stateful widget の追加
- Stateful widget とは widget の lifetime 中に変わりうる状態を管理するもの
- Stateful widget の構成要素
-
StatefulWidget
class
-
State
class のインスタンスを生成する - これ自体は immutable で、破棄されて再生成されうる
-
State
class
- widget の lifetime を超えて存続する
-
- infinite scrolling ListView の使用
- Part2
- リストにアイコン追加
- ListTile のイベントハンドリング
- Navigatorを使った画面遷移
- テーマの変更
必要最低限の要素をうまく詰め込んでいると思う。

とりあえず、それまでのバックグランドに応じて、Flutter for XXXを読むと面白いと思います。
ということで、おさらい。
Flutter for web developers
いろいろ書こうかと思ったけど、基本的に CSS <-> Flutter のマッピングを紹介しているだけ。こういうスタイリングしたい、と思ったら読むといいページ。

Understanding constraints
Constraints go down. Sizes go up. Parent sets position.
Flutter layout can’t really be understood without knowing this rule, so Flutter developers should learn it early on.
このルールが超重要。早い段階で学んでおいた方がよい。
- Constraints go down.
- ウィジェットは自身の制約を親から取得する。
- 制約は、min width, max width, min height, max height の4つの倍精度浮動小数点数のセット。
- ウィジェットは子リストに一つずつ自身の制約を伝えて、各子ウィジェットが必要なサイズを聞く。
- Parent sets position.
- 親ウィジェットは子ウィジェットを1つずつ配置する(X軸に並行に、Y軸に垂直に)。
- Sizes go up.
- 子ウィジェットは親ウィジェットに自身のサイズを伝える。
Limitations
Flutterのレイアウトエンジンにはいくらか重要な制限がある。
- ウィジェットは、その親によって与えられた制約の範囲内でのみ、ウィジェット自体のサイズを決定できる。つまり、ウィジェットは通常、必要なサイズにすることはできない。
- ウィジェットの位置を決定するのはウィジェットの親であるため、ウィジェットは画面内での自身の位置を認識できず、決定しない。
- 親のサイズと位置も親に依存するため、ツリー全体を考慮せずにウィジェットのサイズと位置を正確に定義することは不可能。
- 子ウィジェットが親ウィジェットとは異なるサイズを望んでいて、親がそれを揃えるのに十分な情報を持っていない場合、子供のサイズは無視される可能性がある。配置を定義するときは具体的に。
Examples
-
screen
がルートのウィジェットとみなして、制約のはじまりとなる。screen
直下の子ウィジェットに対しては、screen
と同じサイズになるよう強制する。なので、screen
直下の子ウィジェットでサイズを指定しても無視される。- 子ウィジェットに
Center
などを置いておけば、孫ウィジェット以降は、子ウィジェットの制約の範囲内で、自由にサイズを設定できる。
- 子ウィジェットに
-
ConstrainedBox
は子ウィジェットに対して追加の制約を課すウィジェット。 -
UnconstrainedBox
は子ウィジェットに対して制約を取り払うウィジェット。子ウィジェットのサイズがscreen
サイズを超えることも可能にする(ただしその場合はワーニングが出る)。 -
OverflowBox
はUnconstrainedBox
と似ているが、子ウィジェットのサイズが親ウィジェットのサイズを超えてもワーニングを出さない。 -
LimitedBox
はUnconstrainedBox
配下でのみ、子ウィジェットへの制約を適用することができる。 -
FittedBox
は自身のサイズにフィットするように子ウィジェットのサイズをリサイズする。- もし
FiitedBox
がscreen
直下にある場合、FiitedBox
はscreen
と同じサイズになるよう制約を課されているので、FittedBox
の子ウィジェットはscreen
サイズいっぱいに引き伸ばされる。 - もし
FiitedBox
がCenter
の子ウィジェットである場合、FiitedBox
のサイズはなんでもよい。その場合は、FittedBox
の子ウィジェットのサイズがそのまま適用される。- ただし、子ウィジェットのサイズが
screen
サイズを超える場合、FiitedBox
はscreen
サイズに収まるように、子ウィジェットをリサイズする。
- ただし、子ウィジェットのサイズが
- もし
-
Row
は子ウィジェットに制約を課さない。- なので子ウィジェットのサイズが大きすぎる場合 display warning が出る恐れがある。
- そういった場合は
Expanded
を使うとよい。他の子ウィジェットとの兼ね合いでサイズを拡縮してくれる。 -
Row
の子ウィジェットが全てExpanded
でラップされている場合、等幅でレイアウトされる。
Tight vs. loose constraints
- 厳しい制約は、正確なサイズという1つの可能性を提供する。つまり、厳密な制約の最大幅は最小幅に等しくなる。最大の高さは最小の高さと同じになる。
- 一方、緩い制約は、最大の幅と高さを設定するが、ウィジェットを必要なだけ小さくすることができる。言い換えると、緩い制約の最小幅と高さは両方ともゼロに等しくなる。
-
Cneter
は、親(画面)から取得した厳しい制約を子(コンテナ)の緩い制約に変換するもの、ということができる。
-

一旦「1.公式ドキュメントを読む」はやったので、次は「2. Udacity online Flutter Training」をやっていく。