Pro Yearly is on sale from $80 to $50! »

Flutter はプロダクション開発に耐えうるのか / Flutter ready for production?

Flutter はプロダクション開発に耐えうるのか / Flutter ready for production?

6dd0483f1353a4a359e92633cfd65c64?s=128

Daichi Furiya (Wasabeef)

October 17, 2020
Tweet

Transcript

  1. Flutter はプロダクション開発に耐 えうるのか Google Developers Expert @wasabeef_jp wasabeef CyberAgent, Inc.

  2. Flutter はプロダクション開発に耐えうるのか

  3. • Flutter でプロダクトを作るという判断 • モバイルアプリの開発の現状と課題 • クロスプラットフォームの期待と課題 • アプリ開発で必要な要素 •

    アーキテクチャ • ライブラリ • その他 今日話すこと
  4. Flutter でプロダクトを作るという判断

  5. • モバイルアプリ開発の現状と課題 • クロスプラットフォームの期待と課題 Flutter でプロダクトを作るという判断

  6. モバイルアプリ開発の現状と課題

  7. • モバイルアプリ開発は成熟期でもあるので、致命 的な課題もなく可もなく不可もない現状。 • Jetpack Compose/Swift UI などの宣言的な UI を構築できる仕組みが来年くらいから安定化され

    るたらまた大きな変化が起きるかもしれない。 現状
  8. 過去 〜 Android アプリ開発の黎明期  RetroLambda MVC VOLLEY JUICE ActionBarSherlock Timber

  9. 現在 〜 Android アプリ開発の成熟期  DAGGER2 MVVM FLUX Timber

  10. 現在 〜 Android アプリ開発の成熟期 Activity/Fragment Repository ViewModel LiveData Local Source

    Room/DataStore Remote Data Source Retrofit/okHttp Jetpack Jetpack Jetpack Dagger Hilt Android Studio ここでいう成熟のイメージは アーキテクチャ論争、パフォー マンス改善手法確立がひと段落 し、それらの知見が一般化した 状態であり、アプリ開発(コー ド)の簡略化・テンプレート化 に向かっていることとする。
  11. Jetpack Compose などの宣言的な UI の手法を採 用したことによるパラダイムシフトと、それによる 今後の影響は…? MVVM から Flux/Redux/MVU

    のような状態管理 への移行もあるかもしれない。 宣言的 UI による VIEW のパラダイムシフト
  12. • Android エンジニアの不足?(なんかこれ話題が今週プチバズってた?) • iOS/Android の機能仕様ずれ (SDKやライブラリの差、認識ずれ、、) • 開発期間の長期化(良くも悪くも) 課題

  13. Android エンジニアの不足 ※ 事例 即戦力の中途採用は年間 1 人するのも大変な状態であり、未経験や若 手の育成を重視する方向性にシフトしつつある。 + 10

    ਓ Android Λ࠾༻ʁ iOS 50 ਓ Android 40 ਓ
  14. ポジショントーク(仮) iOSエンジニア or Androidエンジニア? Swift or Kotlin ? Flutter or

    React Native?
  15. クロスプラットフォームへの期待と課題

  16. • アプリ動作の安定性 (クロスプラットフォーム <<= ネイティブ) • 将来性、先行き不安 • iOS/Android で共通の

    UI(悪くも) • iOS/Android の新機能への追従の遅れ? • Flutter と Kotlin MPP のどちらを採用するか? 課題
  17. 将来性、先行き不安 開発元の企業がいかに大 企業だろうとエンジニア コミュニティに受けが良 くないと流行らないとい うことがわかりました。

  18. • 世界的に200万人以上のエンジニアが Flutter を使って いて毎月10%増加している • 利用数上位5地域は インド、中国、米国、EU、ブラジル • Google

    Play に既に100,000個、毎月10,000個以上の Flutter アプリがアップされている 事例 https://medium.com/flutter/flutter-spring-2020-update-f723d898d7af
  19. Flutter の採用事例(国内)

  20. • 2018 年 6 月サービス開始 (Flutter stable 1.0 のリリースは2018年 12

    月) • 担当アプリエンジニア 2 人 REQU
  21. Flutter の採用事例(国外)

  22. • アリババ傘下のフリマアプリ • カメラ機能で商品検索 • アプリ評価 ★ 4.6 DAU 2000万

    • Flutter 事例でユーザ数が世界最大級 ༽჈ (Idle Fish)
  23. iOS/Android で共通の UI(悪くも) Flutter はマテリアルデザインを採用しているの で、悪く言うと iOS っぽいデザインが損なわれてい たりすることがあります。ただ、それは開発速度の 向上のためにデザインシステムは

    Flutter (共通) と して考えた方いいとして思っています。
  24. iOS/Android で共通の UI(悪くも) https://flutter.dev/docs/development/ui/widgets/cupertino Cupertino widgets もある程度存在するが完璧ではないので、iOS らしいデ ザインに完全に踏襲したい場合は、Flutter 以外の選択肢も視野にいれたい。

  25. iOS/Android の新機能への追従の遅れ? 例えば最近の iOS 14、Android 11 への対応は Flutter 1.22.0 でも改善され

    ていますし、致命的には対応が遅れてないという個人的な感覚はあるが、各 OS の新 API のインターフェース公開が後追いで来るのは事実です。
  26. • アプリ動作の安定性がかなり向上 (60 fps) • エンジニアのリソース節約 • 開発期間短縮 • 2020年、開発コミュニティの急速的な拡大

    • iOS/Android で共通の UI(良くも) 期待
  27. エンジニアのリソース節約 サーバエンジニア iOS エンジニア Web エンジニア Android エンジニア 一般的な Swift/Kotlin

    アプリのアサインスタイル
  28. エンジニアのリソース節約 Flutter ͷΞαΠϯελΠϧ アプリエンジニア とりあえず1人以上いれば iOS/ Android アプリ両方開発可能 サーバエンジニア Web

    エンジニア 余剰
  29. エンジニアのリソース節約 サーバエンジニア iOS エンジニア Web エンジニア Android エンジニア 一般的な Swift/Kotlin

    アプリのアサインスタイル それぞれ一人の場合、 コードレビューされない ケースも...
  30. エンジニアのリソース節約 Flutter ͷΞαΠϯελΠϧ サーバエンジニア アプリエンジニア Web エンジニア とりあえず1人以上いれば iOS/ Android

    アプリ両方開発可能 コードレビューできて結果として 品質向上も。
  31. Flutter と Kotlin MPP のどちらを採用するか?

  32. • Google によって開発 • 2018 年 12 月リリース (BREAKING CHANGES

    はありえる) • Dart • ステートフルホットリロード (高速開発) • UI ツールキット(豊富なウィジェット) Flutter
  33. • グラフィックライブラリ • Android, Chrome, Firefox, Blink, Flutter で採用されている •

    Skia は Vulkan をバックエンドエンジンとして変更可能 • Android 9 以降、デフォルトのレンダラーは Skia になってい る(8 と 9 でUIが変わったのはそのため)。Flutter にする とレイヤーが増えるもののレンダラーは同じ Skia
  34. 対応プラットフォーム • Windows 7, 8, 8.1, 10 • macOS 10.10.5

    or later • iOS 8 or later • Android 4.1 (JellyBean) or later • Ubuntu 14.04+, Debian 8+, openSUSE 13.3+, or Fedora Linux 24+ もちろん iOS でも Windows でも動作する Skia
  35. • Swift/Kotlin で良い体験をしてしまったエンジ ニアには Dart の言語実装が足りない。 (Data class, Nested Class,

    Enum Custom Value, Switch expression, protected, alias..) • アーキテクチャの議論が活発(良くも悪くも) • 各 SaaS の SDK が無い場合がある Flutter の難点
  36. Flutter だけだと解決できない例 • 各 SaaS や広告計測系などの Flutter SDK 対応が間に合ってない 場合は自分でラッパー相当を実装する必要があり、その時は

    Kotlin/Swift の知識が必要になる。 • どうしても Flutter からだとコールできない OS 側の機能を使い たい時には PlatformView を使い Flutter アプリ内のウィジェッ トの一部だけをネイティブにすることは出来るが、DRM などの 一部制限があるようなものではそれも出来ない。 例
  37. Flutter だけだと解決できない例 例えばこのアプリが Flutter で作ら れてるとして、動画部分に DRM で HW Secure

    Decoder を使っている ような場合には PlatformViewを 使ったとしても Flutter から呼び出 すのは出来ない。
  38. Flutter だけだと解決できない例 Flutter から MethodChannel API 経由で iOS/Android 側で 実装された画面をまるまる表示

    することが出来るデザインだと 解決が可能になる
  39. Flutter <-->- iOS/Android Flutter から MethodChannel API 経由で iOS/Android 側で

    実装された画面をまるごと表示 することが出来るデザインだと 解決が可能になる
  40. Flutter <-->- iOS/Android ウィジェットの一部分だけを 各 OS 側のものを使うのは出来 ないが各 OS の

    API を呼び出 したり、画面まるごと起動した りは出来る。
  41. Flutter <-->- iOS/Android Flutter (Dart code) Android (Kotlin code) iOS

    (Swift code) Activity を起動 ViewController を起動
  42. • JetBrains によって開発 • UI の共通化はせず、ビジネスロジックの共通化 に特化している(認証、ログなどの共通化) • Kotlin で

    Backends for Frontends Kotlin Multiplatform
  43. JetBrains の野望として はクラサバのロジックを 全て共通化すること。将 来的には UI にも手を出 しそうな情報を小出しし ている。 Kotlin

    Multiplatform Kotlin/LLVM Kotlin/JVM Kotlin/JVM Kotlin/JS Common code
  44. • iOS エンジニアコミュニティに刺さってない • iOS のエンジニアも Kotlin と Gradle を覚えない

    といけない Kotlin Multiplatform の難点
  45. iOS (arm32, arm64, simulator x86_64) macOS (x86_64) Android (arm32, arm64)

    Windows (mingw x86_64, x86) Kotlin/Native - Target Platforms Linux (x86_64, arm32, MIPS, MIPS LE, Raspberry Pi) WebAssembly (x86_64)
  46. Flutter か? Kotlin MPP か? Flutter か? Kotlin MPP か?

  47. Flutter か? Kotlin MPP か? • ゼロから作る新規プロジェクト?

  48. Flutter か? Kotlin MPP か? • ゼロから作る新規プロジェクト? • 既存プロジェクトのリアーキテクチャ?リプレイス?

  49. Flutter か? Kotlin MPP か? • ゼロから作る新規プロジェクト? • 既存プロジェクトのリアーキテクチャ?リプレイス? •

    アプリ開発に当てれるエンジニアの人数は?
  50. Flutter か? Kotlin MPP か? • ゼロから作る新規プロジェクト? • 既存プロジェクトのリアーキテクチャ?リプレイス? •

    アプリ開発に当てれるエンジニアの人数は? • エンジニアの技術レベル感は?
  51. Flutter か? Kotlin MPP か? • ゼロから作る新規プロジェクト? • 既存プロジェクトのリアーキテクチャ?リプレイス? •

    アプリ開発に当てれるエンジニアの人数は? • エンジニアの技術レベル感は? • 安定的な技術志向か?リスクをとった挑戦志向か?
  52. Flutter か? Kotlin MPP か? • ゼロから作る新規プロジェクト? • 既存プロジェクトのリアーキテクチャ?リプレイス? •

    アプリ開発に当てれるエンジニアの人数は? • エンジニアの技術レベル感は? • 安定的な技術志向か?リスクをとった挑戦志向か? • プロジェクト・プロダクトのスケールを強く意識するか?
  53. Flutter か? Kotlin MPP か? • ゼロから作る新規プロジェクト? • 既存プロジェクトのリアーキテクチャ?リプレイス? •

    アプリ開発に当てれるエンジニアの人数は? • エンジニアの技術レベル感は? • 安定的な技術志向か?リスクをとった挑戦志向か? • プロジェクト・プロダクトのスケールを強く意識するか? • とにかく早くリリースしたい?
  54. Flutter か? Kotlin MPP か? • ゼロから作る新規プロジェクト? • 既存プロジェクトのリアーキテクチャ?リプレイス? •

    アプリ開発に当てれるエンジニアの人数は? • エンジニアの技術レベル感は? • 安定的な技術志向か?リスクをとった挑戦志向か? • プロジェクト・プロダクトのスケールを強く意識するか? • とにかく早くリリースしたい?
  55. Flutter か? Kotlin MPP か?  Flutter   Kotlin MPP  • 新規プロジェクト

    • 少人数(1〜4人) • 少人数でも両プラットフォーム でブランディングの一貫性を維 持したい • とにかく早くリリースしたい • よりチャレンジしたい • 新規/既存プロジェクト • 大人数(10人〜) • iOS/Androidアプリ開発の精 通している • リスクを抑えたい • 各プラットフォームで分けて デザインを拘りたい 例 例
  56. Flutter か? Kotlin MPP か? 結論 プロダクトの仕様、プロジェクトの規模、エンジニアの 能力によって様々なケースがある。という結論

  57. Hello World のその先へ

  58. アプリ開発で必要な要素

  59. • アーキテクチャ • ライブラリ • アーキテクチャを実現するための • カスタムウィジェットを表現するための • その他

    アプリ開発で必要な要素
  60. Architecture

  61. Architecture それぞれのアーキテクチャが目 指していることが違うので、シ ステムのライフサイクルによっ て相性の良し悪しはあります。 ただ、それが絶対的な正解はあ りません。チームの成熟度や趣 味思考を考えた結果であれば、 何を選んでも良いと思います し、自分で新たに生み出すのも

    良いと思います。 MVVM Bloc Redux ELM/MVU
  62. MVVM + Repository View Repository ViewModel Local Source Remote Data

    Source このスライドでは Android エンジニアの馴 染みが一番あるであろう MVVM + Repository を 例として取り上げていこ うと思います。 MVVM Repository
  63. MVVM UI の実装において、例えばテキストを入力し、バリーデーション、データを保持し、ボタン をタップして、サーバに送信するようなコードを View に全て追加していくと UI が複雑に なっていった時には更にコードが肥大化してしまい、それは UI

    とプレゼンテーションロジッ クとビジネスロジックの密結合になっているのでメンテナンスが大変ですし、テストを書く が困難に思えます。 そこで必要になってくる概念が関心の分離 (SoC) です。 簡単に説明す ると全てのアーキテクチャ共通して言えることですが、何をさせたいのか?その役割によっ て分離した構成要素とすることです。
  64. MVVM MVVM は Model–View–ViewModel のことを指し、その構成要素の基本形は以下となっています。 • View は UI (Widget)

    を描画(出力)し、ユーザからの入力データを受け取ります。 • ViewModel は View から入力された状態(データ)を適切に変換して Model として持ちます。 また、Model の状態(データ)を View 渡して画面の更新を促します。 • Model は状態(データ)を保持し、それがどう変換されて画面に描画されるかは知りません。
  65. Repository Repository Local Source Remote Data Source Repository pattern はデータソース

    へのアクセスを抽象化するためのデ ザインパターンです。ViewModel が 持つことになりますが、ViewModel 側からすると Repository とデータ の形式だけを取り決めるだけで、入 手先がサーバからなのか、ローカル の DB なのか、オンメモリなのかな どは知りません。
  66. MVVM + Repository View Repository ViewModel Local Source Remote Data

    Source Android で現在一般的な アーキテクチャは MVVM に Repository Pattern を合わせた設計 となっています。 MVVM Repository 
  67. DI/Service Locator

  68. DI/Service Locator View Repository ViewModel Local Source Remote Data Source

    DI/SL クラス間の密結合を減らして、 再利用性を高めるための手法。 すごくポピュラーな例をいうと テスト書きたいので、テスト実 行時はサーバ API を叩くので はなくて、モックデータを読み 込むような処理に変えたいがた めに使います。 (テスタビリティの向上)
  69. 主な DI/Service Locator のパッケージ  InheritedWidget   Riverpod package  • Flutter SDK

    に内包 • BuildContext が必要 • 子ウィジェットからでも O(1) でオブジェクトが取得できる • 少しローレベルなクラス • 有名な方が個人開発 • 新しい Provider でシンプル • まだ安定版ではない • 今や Dagger みたいな位置付 • コンパイルセーフ • Flutter に依存せずにも使える https://github.com/rrousselGit/river_pod https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html
  70. Riverpod # pubspec.yaml dependencies: flutter_riverpod: ^0.11.x pubspec.yaml に依存関係を追加して、flutter pub get

    をする https://github.com/rrousselGit/river_pod $ flutter pub get
  71. Riverpod https://github.com/rrousselGit/river_pod final myNotifierProvider = ChangeNotifierProvider((_) { return MyNotifier(); });

    class MyNotifier extends ChangeNotifier { int count; /// TODO: typical ChangeNotifier logic } この例では ChangeNotifier を継承した MyNotifier を Riverpod に管理しても らいます。Riverpod には ChangerNotifierProvider というものが用意されてい るので、そこで MyNotifier のインスタンスを返却します。
  72. Riverpod https://github.com/rrousselGit/river_pod main.dart にて、MyApp を Riverpod のクラスである ProviderScope で囲いま しょう。このスコープの設定がないとランタイムエラーになります。

    void main() { runApp( const ProviderScope(child: MyApp()), ); }
  73. Riverpod https://github.com/rrousselGit/river_pod class MainPage extends ConsumerWidget { @override Widget build(BuildContext

    context, ScopedReader watch) { final count = watch(myNotifierProvider); return Text(count.toString()); } } Riverpod の ConsumerWidget を継承したウィジェット内であれば、シンプル に値の監視をすることができます。MyNotifier の値が変わっていれば、この build が再実行されます。
  74. State management

  75. State management View Repository ViewModel Local Source Remote Data Source

    DI 主に View とViewModel 間 で状態の共有を行うことが 目的となっています。View 側は状態が変わったことを 知りたいので ViewModel から通知をもらうようなイ メージになります。
  76. State management 右の簡単なアプリを例にします。 このアプリはカタログとカートに画面 が分かれています。各アイテムの [ADD] をタップすることで、カート にアイテムが追加される想定です。 https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple

  77. State management そのウィジェットツリーを表現するとこ のようになっており、それぞれクラスが 分かれていたとします。 [ADD] ボタン自体は MyListItem クラス が制御を管理しているので、どうやって

    MyCart クラスに通知するかを考えないと いけません。 Observable に該当する仕組みが必要で す。 https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple
  78. State management https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple そのウィジェットツリーを表現するとこ のようになっており、それぞれクラスが 分かれていたとします。 [ADD] ボタン自体は MyListItem クラス

    が制御を管理しているので、どうやって MyCart クラスに通知するかを考えないと いけません。 Observable に該当する仕組みが必要で す。
  79. State management  ChangeNotifier   StateNotifier package  • Flutter SDK に内包 •

    状態を複数管理できる • 割と自由にできる • その状態は Mutable • 状態の変更を通知できる • Riverpod に合わせて使える • 有名な方が個人開発 • ValueNotifier の進化版 • 状態(state)を一つだけ管理 • その状態は Immutable • 状態の変更を通知できる • Freezed で copyWith を自動 生成してもらうと良い • Riverpod に合わせて使える Android の LiveData のような役割
  80. ChangeNotifier を継承した ViewModel final homeViewModelNotifierProvider = ChangeNotifierProvider( (ref) =>= HomeViewModel(repository:

    ref.read(newsRepositoryProvider))); class HomeViewModel extends ChangeNotifier { HomeViewModel({@required NewsRepository repository}) : _repository = repository; final NewsRepository _repository; News _news; News get news =>= _news; Future<void> fetchNews() async { _news = _repository.getNews(); notifyListeners() } } 全体的に少しシンプルにしてありますが、HomeViewModel は ChangeNotifier を継承します。
  81. ChangeNotifier を継承した ViewModel final homeViewModelNotifierProvider = ChangeNotifierProvider( (ref) =>= HomeViewModel(repository:

    ref.read(newsRepositoryProvider))); class HomeViewModel extends ChangeNotifier { HomeViewModel({@required NewsRepository repository}) : _repository = repository; final NewsRepository _repository; News _news; News get news =>= _news; Future<void> fetchNews() async { _news = _repository.getNews(); notifyListeners() } } StateNotifier の場合は管理対象の状態は state を実装が必要になりますが、ChangeNotifier は特に何も。
  82. ChangeNotifier を継承した ViewModel final homeViewModelNotifierProvider = ChangeNotifierProvider( (ref) =>= HomeViewModel(repository:

    ref.read(newsRepositoryProvider))); class HomeViewModel extends ChangeNotifier { HomeViewModel({@required NewsRepository repository}) : _repository = repository; final NewsRepository _repository; News _news; News get news =>= _news; Future<void> fetchNews() async { _news = _repository.getNews(); notifyListeners() } } Repository で取得したデータを格納しただけでは、リスナーに通知はされません。
  83. ChangeNotifier を継承した ViewModel final homeViewModelNotifierProvider = ChangeNotifierProvider( (ref) =>= HomeViewModel(repository:

    ref.read(newsRepositoryProvider))); class HomeViewModel extends ChangeNotifier { HomeViewModel({@required NewsRepository repository}) : _repository = repository; final NewsRepository _repository; News _news; News get news =>= _news; Future<void> fetchNews() async { _news = _repository.getNews(); notifyListeners() } } notifyListeners() をコールすることで、通知がいきます。
  84. ChangeNotifier を継承した ViewModel class MainPage extends ConsumerWidget { @override Widget

    build(BuildContext context, ScopedReader watch) { final news = watch(homeViewModelNotifierProvider); return Text(news.title); } } 先ほどの Riverpod の説明のところで紹介したものと同じです。
  85. Networking

  86. Networking View Repository ViewModel Local Source Remote Data Source DI

    主に Remote Data Source でサーバの API  を叩くために Endpoint, Header, Token, Body の制 御を行います。
  87. 主な Http client のパッケージ  http package   dio package  • 公式に

    Google が開発 • メンテは活発 • シンプルな Http client で単純 なことをやるならこれでも十分 • Flutter China コミュニティ が開発(主に一人) • メンテが若干不安 • 機能が豊富で Cancel, Cache や Cookie の制御や retrofit like なジェネレータもある • で人気がある https://github.com/flutterchina/dio https://github.com/dart-lang/http
  88. dio + Cache https://github.com/flutterchina/dio # data_source.dart import 'package:dio/dio.dart'; @override Future<News>

    getNews() async { return _dio.get<Map<String, dynamic>>>( '/v1/wasabeef', queryParameters: <String, String>{ 'apiKey': 'VEhJUyBJUyBBUElLRVk', }, options: buildCacheOptions(const Duration(hours: 1)), ) .then((response) =>= News.fromJson(response.data)); } # pubspec.yaml dependencies: dio: ^3.x.x dio_http_cache: ^0.2.x 何かしら他の分野でも Http client を使ったこと ある人であれば理解は難し くないと思います。
  89. Serializable/Deserialize

  90. Serializable/Deserialize View Repository ViewModel Local Source Remote Data Source DI

    特にサーバ API 通信で使 われる送受信したデータを シリアライズとデシリアラ イズ。
  91. 主な Serializable/Deserialize のパッケージ  json_serializable package   Freezed package  • 公式に Google

    が開発 • アノテーションを元に自動生成 • to/from JSON • 有名な方が個人開発 • json_serializable のサポートし ている • アノテーションを元に自動生成 • toString, hashCode.. • copyWith • Immutable https://github.com/rrousselGit/freezed https://github.com/google/json_serializable.dart
  92. Freezed part 'article.freezed.dart'; part 'article.g.dart'; @freezed abstract class Article with

    _$Article { factory Article({ @required Source source, String author, @required String title, @required String description, @required String url, String urlToImage, @required DateTime publishedAt, String content, }) = _Article; factory Article.fromJson(Map<String, dynamic> json) =>= _$ArticleFromJson(json); } この例では、@freezed アノ テーションをつけて、 _$Article (自動生成されるク ラス)の mixin を適用していま す。 Freezed は json_serializable にも対応しているので、 _$ArticleFromJson のイン ターフェースも生成されていま す。 https://github.com/rrousselGit/freezed
  93. Assets/Fonts

  94. Assets/Fonts View Repository ViewModel Local Source Remote Data Source DI

    アプリ内で画像やフォ ントなどのファイルを 使いたい場合の設定を 説明していきます。
  95. Assets - ローカル画像ファイルへのアクセス # pubspec.yaml flutter: assets: - assets/images/ -

    assets/images/icons/ pubspec.yaml に画像ファイルを置いたところのパスを assets: に指定します。 ディレクトリを指定した場合は、そのディレクトリ内は全て精査されますが、サ ブディレクトリ内までを再帰的には精査しません。
  96. Assets - ローカル画像ファイルへのアクセス デバイスのピクセル密度毎によって 2.0x, 3.0x のディレクトリに配置します。 ※pubspec.yaml に指定する必要はありません。

  97. Android (AAPT) の R.java に該当するもの が Flutter の世界では公式にはなく、画像な どのリソースへのアクセスはファイルパスを 文字列で

    ”assets/images/profile.jpg” で指定 しないといけません。 Assets - ローカル画像ファイルへのアクセス
  98. Assets - ローカル画像ファイルへのアクセス /// main.dart Widget build(BuildContext context) { return

    Image.asset(‘assets/images/icons/profile.jpg'); } 例えば、Image class にローカルの画像を指定したい場合には以下のようにパス を指定します。
  99. Assets - ローカル画像ファイルへのアクセス /// main.dart Widget build(BuildContext context) { return

    Image.asset(‘assets/images/icons/profile.jpg'); } ただ、文字列で指定するのはとてもタイプセーフだと言えず R.java って良くで きた仕組みだなぁって感じることとなります。。
  100. Fonts - ローカルフォントへのアクセス # pubspec.yaml flutter: fonts: - family: RobotoMono

    fonts: - asset: assets/fonts/RobotoMono-Regular.ttf - asset: assets/fonts/RobotoMono-Bold.ttf weight: 700 好きな Fonts を使いたい場合にも pubspec.yaml に指定が必要となります
  101. Fonts - ローカルフォントへのアクセス /// main.dart Widget build(BuildContext context) { return

    Text( 'Hi there', style: TextStyle( fontFamily: 'RobotoMono', ), } フォントもファミリー名を文字列で指定します。
  102. もしタイポしていた場合 拡張子が間違っていたなどのタイポ(❌ jpeg、⭕ jpg)でも ランタイムエラーになるので、気をつけないといけません。 The following assertion was thrown

    resolving an image codec: Unable to load asset: assets/images/profile.jpeg /// main.dart Widget build(BuildContext context) { return Image.asset(‘assets/images/icons/profile.jpeg'); }
  103. R.java, R.swift, SwiftGen, FlutterGen プロモーションを含みます

  104. FlutterGen /// main.dart Widget build(BuildContext context) { return Image.asset(‘assets/images/icons/profile.jpg'); }

    FlutterGen を使えば、コマンド一つでタイプセーフにクラスを自動生成します プロモーションを含みます /// main.dart Widget build(BuildContext context) { return Assets.images.profile.image(); }
  105. FlutterGen /// main.dart TextStyle(fontFamily: FontFamily.robotoMono), フォントも自動生成されます /// main.dart TextStyle(fontFamily: 'RobotoMono')

    プロモーションを含みます
  106. FlutterGen プロモーションを含みます FlutterGen https://github.com/FlutterGen/flutter_gen さらに詳しく知りたい場合は

  107. Test

  108. Mockito /// Real class class Dog { String sound() =>=

    "Woof"; } /// Mock class class MockCat extends Mock implements Cat {} test('Dog Sound Test', () async { var dog = MockDog(); dog.sound(); verify(dog.sound()); when(dog.sound()).thenReturn("Grrrr"); expect(dog.sound(), "Grrrr"); }); https://github.com/dart-lang/mockito Android アプリ開発 でもよく使われるモッ ク化ライブラリの Mockito の Dart 版 が Google 公式とし て公開されているの で、最初はこのパッ ケージを導入してみる ことをお勧めします。
  109. Lint/Analyze

  110. 複数人でプロダクション開発していく上では 特に、コードの可読性や保守性を保つために はコード規約に則って維持していくことが当 たり前の時代になりました Lint/Analyze

  111. Effective Dart style # main.dart library peg_parser.source_scanner; import 'file_system.dart'; import

    'slider_menu.dart'; # main.dart library pegparser.SourceScanner; import 'file-system.dart'; import 'SliderMenu.dart'; 例:Lower snake case でディレクトリやファイル名をつけること。
  112. Linter, Analyzer 設定 プロジェクトルートに analysis_options.yaml を作成することでルールの設定が可能になります # analysis_options.yaml analyzer: exclude:

    - "**/*.g.dart" strong-mode: implicit-casts: false implicit-dynamic: false ..... linter: rules: - camel_case_types .....
  113.  effective_dart style  Effective Dart に準拠 した Lint ルール Linter, Analyzer

    設定  pedantic style  Google 内部で採用され ている Lint ルール  flutter style  Flutter analyze コマン ドで適用されている Lint ルール https://dart-lang.github.io/linter/lints/index.html
  114. Flutter Architecture Blueprints プロモーションを含みます https://github.com/wasabeef/flutter-architecture-blueprints これらのサンプルコードを見たい方は

  115. References * Docs https://flutter.dev/ * Samples https://github.com/brianegan/flutter_architecture_samples * Images https://unsplash.com/

    https://www.irasutoya.com/
  116. @wasabeef_jp wasabeef