Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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

Daichi Furiya (Wasabeef)

October 17, 2020
Tweet

More Decks by Daichi Furiya (Wasabeef)

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

  3. • Flutter でプロダクトを作るという判断
    • モバイルアプリの開発の現状と課題
    • クロスプラットフォームの期待と課題
    • アプリ開発で必要な要素
    • アーキテクチャ
    • ライブラリ
    • その他
    今日話すこと

    View Slide

  4. Flutter でプロダクトを作るという判断

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  8. 過去 〜 Android アプリ開発の黎明期 
    RetroLambda
    MVC
    VOLLEY
    JUICE
    ActionBarSherlock
    Timber

    View Slide

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

    View Slide

  10. 現在 〜 Android アプリ開発の成熟期
    Activity/Fragment
    Repository
    ViewModel
    LiveData
    Local Source
    Room/DataStore
    Remote Data Source
    Retrofit/okHttp
    Jetpack
    Jetpack
    Jetpack
    Dagger Hilt
    Android Studio
    ここでいう成熟のイメージは
    アーキテクチャ論争、パフォー
    マンス改善手法確立がひと段落
    し、それらの知見が一般化した
    状態であり、アプリ開発(コー
    ド)の簡略化・テンプレート化
    に向かっていることとする。

    View Slide

  11. Jetpack Compose などの宣言的な UI の手法を採
    用したことによるパラダイムシフトと、それによる
    今後の影響は…?
    MVVM から Flux/Redux/MVU のような状態管理
    への移行もあるかもしれない。
    宣言的 UI による VIEW のパラダイムシフト

    View Slide

  12. • Android エンジニアの不足?(なんかこれ話題が今週プチバズってた?)
    • iOS/Android の機能仕様ずれ
    (SDKやライブラリの差、認識ずれ、、)
    • 開発期間の長期化(良くも悪くも)
    課題

    View Slide

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

    View Slide

  14. ポジショントーク(仮)
    iOSエンジニア or Androidエンジニア?
    Swift or Kotlin ?
    Flutter or React Native?

    View Slide

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

    View Slide

  16. • アプリ動作の安定性 (クロスプラットフォーム <<= ネイティブ)
    • 将来性、先行き不安
    • iOS/Android で共通の UI(悪くも)
    • iOS/Android の新機能への追従の遅れ?
    • Flutter と Kotlin MPP のどちらを採用するか?
    課題

    View Slide

  17. 将来性、先行き不安
    開発元の企業がいかに大
    企業だろうとエンジニア
    コミュニティに受けが良
    くないと流行らないとい
    うことがわかりました。

    View Slide

  18. • 世界的に200万人以上のエンジニアが Flutter を使って
    いて毎月10%増加している
    • 利用数上位5地域は インド、中国、米国、EU、ブラジル
    • Google Play に既に100,000個、毎月10,000個以上の
    Flutter アプリがアップされている
    事例
    https://medium.com/flutter/flutter-spring-2020-update-f723d898d7af

    View Slide

  19. Flutter の採用事例(国内)

    View Slide

  20. • 2018 年 6 月サービス開始
    (Flutter stable 1.0 のリリースは2018年 12 月)
    • 担当アプリエンジニア 2 人
    REQU

    View Slide

  21. Flutter の採用事例(国外)

    View Slide

  22. • アリババ傘下のフリマアプリ
    • カメラ機能で商品検索
    • アプリ評価 ★ 4.6 DAU 2000万
    • Flutter 事例でユーザ数が世界最大級
    ༽჈ (Idle Fish)

    View Slide

  23. iOS/Android で共通の UI(悪くも)
    Flutter はマテリアルデザインを採用しているの
    で、悪く言うと iOS っぽいデザインが損なわれてい
    たりすることがあります。ただ、それは開発速度の
    向上のためにデザインシステムは Flutter (共通) と
    して考えた方いいとして思っています。

    View Slide

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

    View Slide

  25. iOS/Android の新機能への追従の遅れ?
    例えば最近の iOS 14、Android 11 への対応は Flutter 1.22.0 でも改善され
    ていますし、致命的には対応が遅れてないという個人的な感覚はあるが、各
    OS の新 API のインターフェース公開が後追いで来るのは事実です。

    View Slide

  26. • アプリ動作の安定性がかなり向上 (60 fps)
    • エンジニアのリソース節約
    • 開発期間短縮
    • 2020年、開発コミュニティの急速的な拡大
    • iOS/Android で共通の UI(良くも)
    期待

    View Slide

  27. エンジニアのリソース節約
    サーバエンジニア
    iOS エンジニア
    Web エンジニア
    Android エンジニア
    一般的な Swift/Kotlin アプリのアサインスタイル

    View Slide

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

    View Slide

  29. エンジニアのリソース節約
    サーバエンジニア
    iOS エンジニア
    Web エンジニア
    Android エンジニア
    一般的な Swift/Kotlin アプリのアサインスタイル
    それぞれ一人の場合、
    コードレビューされない
    ケースも...

    View Slide

  30. エンジニアのリソース節約
    Flutter ͷΞαΠϯελΠϧ
    サーバエンジニア
    アプリエンジニア
    Web エンジニア
    とりあえず1人以上いれば iOS/
    Android アプリ両方開発可能
    コードレビューできて結果として
    品質向上も。

    View Slide

  31. Flutter と Kotlin MPP のどちらを採用するか?

    View Slide

  32. • Google によって開発
    • 2018 年 12 月リリース
    (BREAKING CHANGES はありえる)
    • Dart
    • ステートフルホットリロード (高速開発)
    • UI ツールキット(豊富なウィジェット)
    Flutter

    View Slide

  33. • グラフィックライブラリ
    • Android, Chrome, Firefox, Blink, Flutter で採用されている
    • Skia は Vulkan をバックエンドエンジンとして変更可能
    • Android 9 以降、デフォルトのレンダラーは Skia になってい
    る(8 と 9 でUIが変わったのはそのため)。Flutter にする
    とレイヤーが増えるもののレンダラーは同じ
    Skia

    View Slide

  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

    View Slide

  35. • Swift/Kotlin で良い体験をしてしまったエンジ
    ニアには Dart の言語実装が足りない。
    (Data class, Nested Class, Enum Custom Value, Switch expression, protected, alias..)
    • アーキテクチャの議論が活発(良くも悪くも)
    • 各 SaaS の SDK が無い場合がある
    Flutter の難点

    View Slide

  36. Flutter だけだと解決できない例
    • 各 SaaS や広告計測系などの Flutter SDK 対応が間に合ってない
    場合は自分でラッパー相当を実装する必要があり、その時は
    Kotlin/Swift の知識が必要になる。
    • どうしても Flutter からだとコールできない OS 側の機能を使い
    たい時には PlatformView を使い Flutter アプリ内のウィジェッ
    トの一部だけをネイティブにすることは出来るが、DRM などの
    一部制限があるようなものではそれも出来ない。 例

    View Slide

  37. Flutter だけだと解決できない例
    例えばこのアプリが Flutter で作ら
    れてるとして、動画部分に DRM で
    HW Secure Decoder を使っている
    ような場合には PlatformViewを
    使ったとしても Flutter から呼び出
    すのは出来ない。

    View Slide

  38. Flutter だけだと解決できない例
    Flutter から MethodChannel
    API 経由で iOS/Android 側で
    実装された画面をまるまる表示
    することが出来るデザインだと
    解決が可能になる

    View Slide

  39. Flutter <-->- iOS/Android
    Flutter から MethodChannel
    API 経由で iOS/Android 側で
    実装された画面をまるごと表示
    することが出来るデザインだと
    解決が可能になる

    View Slide

  40. Flutter <-->- iOS/Android
    ウィジェットの一部分だけを
    各 OS 側のものを使うのは出来
    ないが各 OS の API を呼び出
    したり、画面まるごと起動した
    りは出来る。

    View Slide

  41. Flutter <-->- iOS/Android
    Flutter (Dart code)
    Android (Kotlin code) iOS (Swift code)
    Activity を起動 ViewController を起動

    View Slide

  42. • JetBrains によって開発
    • UI の共通化はせず、ビジネスロジックの共通化
    に特化している(認証、ログなどの共通化)
    • Kotlin で Backends for Frontends
    Kotlin Multiplatform

    View Slide

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

    View Slide

  44. • iOS エンジニアコミュニティに刺さってない
    • iOS のエンジニアも Kotlin と Gradle を覚えない
    といけない
    Kotlin Multiplatform の難点

    View Slide

  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)

    View Slide

  46. Flutter か? Kotlin MPP か?
    Flutter か? Kotlin MPP か?

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  55. Flutter か? Kotlin MPP か?
     Flutter   Kotlin MPP 
    • 新規プロジェクト
    • 少人数(1〜4人)
    • 少人数でも両プラットフォーム
    でブランディングの一貫性を維
    持したい
    • とにかく早くリリースしたい
    • よりチャレンジしたい
    • 新規/既存プロジェクト
    • 大人数(10人〜)
    • iOS/Androidアプリ開発の精
    通している
    • リスクを抑えたい
    • 各プラットフォームで分けて
    デザインを拘りたい
    例 例

    View Slide

  56. Flutter か? Kotlin MPP か?
    結論
    プロダクトの仕様、プロジェクトの規模、エンジニアの
    能力によって様々なケースがある。という結論

    View Slide

  57. Hello World のその先へ

    View Slide

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

    View Slide

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

    View Slide

  60. Architecture

    View Slide

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

    View Slide

  62. MVVM + Repository
    View
    Repository
    ViewModel
    Local Source Remote Data Source
    このスライドでは
    Android エンジニアの馴
    染みが一番あるであろう
    MVVM + Repository を
    例として取り上げていこ
    うと思います。
    MVVM
    Repository

    View Slide

  63. MVVM
    UI の実装において、例えばテキストを入力し、バリーデーション、データを保持し、ボタン
    をタップして、サーバに送信するようなコードを View に全て追加していくと UI が複雑に
    なっていった時には更にコードが肥大化してしまい、それは UI とプレゼンテーションロジッ
    クとビジネスロジックの密結合になっているのでメンテナンスが大変ですし、テストを書く
    が困難に思えます。 そこで必要になってくる概念が関心の分離 (SoC) です。 簡単に説明す
    ると全てのアーキテクチャ共通して言えることですが、何をさせたいのか?その役割によっ
    て分離した構成要素とすることです。

    View Slide

  64. MVVM
    MVVM は Model–View–ViewModel のことを指し、その構成要素の基本形は以下となっています。
    • View は UI (Widget) を描画(出力)し、ユーザからの入力データを受け取ります。
    • ViewModel は View から入力された状態(データ)を適切に変換して Model として持ちます。
    また、Model の状態(データ)を View 渡して画面の更新を促します。
    • Model は状態(データ)を保持し、それがどう変換されて画面に描画されるかは知りません。

    View Slide

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

    View Slide

  66. MVVM + Repository
    View
    Repository
    ViewModel
    Local Source Remote Data Source
    Android で現在一般的な
    アーキテクチャは
    MVVM に Repository
    Pattern を合わせた設計
    となっています。
    MVVM
    Repository 

    View Slide

  67. DI/Service Locator

    View Slide

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

    View Slide

  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

    View Slide

  70. Riverpod
    # pubspec.yaml
    dependencies:
    flutter_riverpod: ^0.11.x
    pubspec.yaml に依存関係を追加して、flutter pub get をする
    https://github.com/rrousselGit/river_pod
    $ flutter pub get

    View Slide

  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 のインスタンスを返却します。

    View Slide

  72. Riverpod
    https://github.com/rrousselGit/river_pod
    main.dart にて、MyApp を Riverpod のクラスである ProviderScope で囲いま
    しょう。このスコープの設定がないとランタイムエラーになります。
    void main() {
    runApp(
    const ProviderScope(child: MyApp()),
    );
    }

    View Slide

  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 が再実行されます。

    View Slide

  74. State management

    View Slide

  75. State management
    View
    Repository
    ViewModel
    Local Source Remote Data Source
    DI
    主に View とViewModel 間
    で状態の共有を行うことが
    目的となっています。View
    側は状態が変わったことを
    知りたいので ViewModel
    から通知をもらうようなイ
    メージになります。

    View Slide

  76. State management
    右の簡単なアプリを例にします。
    このアプリはカタログとカートに画面
    が分かれています。各アイテムの
    [ADD] をタップすることで、カート
    にアイテムが追加される想定です。
    https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple

    View Slide

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

    View Slide

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

    View Slide

  79. State management
     ChangeNotifier   StateNotifier package 
    • Flutter SDK に内包
    • 状態を複数管理できる
    • 割と自由にできる
    • その状態は Mutable
    • 状態の変更を通知できる
    • Riverpod に合わせて使える
    • 有名な方が個人開発
    • ValueNotifier の進化版
    • 状態(state)を一つだけ管理
    • その状態は Immutable
    • 状態の変更を通知できる
    • Freezed で copyWith を自動
    生成してもらうと良い
    • Riverpod に合わせて使える
    Android の LiveData のような役割

    View Slide

  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 fetchNews() async {
    _news = _repository.getNews();
    notifyListeners()
    }
    }
    全体的に少しシンプルにしてありますが、HomeViewModel は ChangeNotifier を継承します。

    View Slide

  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 fetchNews() async {
    _news = _repository.getNews();
    notifyListeners()
    }
    }
    StateNotifier の場合は管理対象の状態は state を実装が必要になりますが、ChangeNotifier は特に何も。

    View Slide

  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 fetchNews() async {
    _news = _repository.getNews();
    notifyListeners()
    }
    }
    Repository で取得したデータを格納しただけでは、リスナーに通知はされません。

    View Slide

  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 fetchNews() async {
    _news = _repository.getNews();
    notifyListeners()
    }
    }
    notifyListeners() をコールすることで、通知がいきます。

    View Slide

  84. ChangeNotifier を継承した ViewModel
    class MainPage extends ConsumerWidget {
    @override
    Widget build(BuildContext context, ScopedReader watch) {
    final news = watch(homeViewModelNotifierProvider);
    return Text(news.title);
    }
    }
    先ほどの Riverpod の説明のところで紹介したものと同じです。

    View Slide

  85. Networking

    View Slide

  86. Networking
    View
    Repository
    ViewModel
    Local Source Remote Data Source
    DI
    主に Remote Data
    Source でサーバの API 
    を叩くために Endpoint,
    Header, Token, Body の制
    御を行います。

    View Slide

  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

    View Slide

  88. dio + Cache
    https://github.com/flutterchina/dio
    # data_source.dart
    import 'package:dio/dio.dart';
    @override
    Future getNews() async {
    return _dio.get>>(
    '/v1/wasabeef',
    queryParameters: {
    '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 を使ったこと
    ある人であれば理解は難し
    くないと思います。

    View Slide

  89. Serializable/Deserialize

    View Slide

  90. Serializable/Deserialize
    View
    Repository
    ViewModel
    Local Source Remote Data Source
    DI
    特にサーバ API 通信で使
    われる送受信したデータを
    シリアライズとデシリアラ
    イズ。

    View Slide

  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

    View Slide

  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 json) =>=
    _$ArticleFromJson(json);
    }
    この例では、@freezed アノ
    テーションをつけて、
    _$Article (自動生成されるク
    ラス)の mixin を適用していま
    す。
    Freezed は json_serializable
    にも対応しているので、
    _$ArticleFromJson のイン
    ターフェースも生成されていま
    す。
    https://github.com/rrousselGit/freezed

    View Slide

  93. Assets/Fonts

    View Slide

  94. Assets/Fonts
    View
    Repository
    ViewModel
    Local Source Remote Data Source
    DI
    アプリ内で画像やフォ
    ントなどのファイルを
    使いたい場合の設定を
    説明していきます。

    View Slide

  95. Assets - ローカル画像ファイルへのアクセス
    # pubspec.yaml
    flutter:
    assets:
    - assets/images/
    - assets/images/icons/
    pubspec.yaml に画像ファイルを置いたところのパスを assets: に指定します。
    ディレクトリを指定した場合は、そのディレクトリ内は全て精査されますが、サ
    ブディレクトリ内までを再帰的には精査しません。

    View Slide

  96. Assets - ローカル画像ファイルへのアクセス
    デバイスのピクセル密度毎によって 2.0x, 3.0x のディレクトリに配置します。
    ※pubspec.yaml に指定する必要はありません。

    View Slide

  97. Android (AAPT) の R.java に該当するもの
    が Flutter の世界では公式にはなく、画像な
    どのリソースへのアクセスはファイルパスを
    文字列で ”assets/images/profile.jpg” で指定
    しないといけません。
    Assets - ローカル画像ファイルへのアクセス

    View Slide

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

    View Slide

  99. Assets - ローカル画像ファイルへのアクセス
    /// main.dart
    Widget build(BuildContext context) {
    return Image.asset(‘assets/images/icons/profile.jpg');
    }
    ただ、文字列で指定するのはとてもタイプセーフだと言えず R.java って良くで
    きた仕組みだなぁって感じることとなります。。

    View Slide

  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 に指定が必要となります

    View Slide

  101. Fonts - ローカルフォントへのアクセス
    /// main.dart
    Widget build(BuildContext context) {
    return Text(
    'Hi there',
    style: TextStyle(
    fontFamily: 'RobotoMono',
    ),
    }
    フォントもファミリー名を文字列で指定します。

    View Slide

  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');
    }

    View Slide

  103. R.java, R.swift, SwiftGen, FlutterGen
    プロモーションを含みます

    View Slide

  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();
    }

    View Slide

  105. FlutterGen
    /// main.dart
    TextStyle(fontFamily: FontFamily.robotoMono),
    フォントも自動生成されます
    /// main.dart
    TextStyle(fontFamily: 'RobotoMono')
    プロモーションを含みます

    View Slide

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

    View Slide

  107. Test

    View Slide

  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 公式とし
    て公開されているの
    で、最初はこのパッ
    ケージを導入してみる
    ことをお勧めします。

    View Slide

  109. Lint/Analyze

    View Slide

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

    View Slide

  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 でディレクトリやファイル名をつけること。


    View Slide

  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
    .....

    View Slide

  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

    View Slide

  114. Flutter Architecture Blueprints
    プロモーションを含みます
    https://github.com/wasabeef/flutter-architecture-blueprints
    これらのサンプルコードを見たい方は

    View Slide

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

    View Slide

  116. @wasabeef_jp
    wasabeef

    View Slide