Open8
【Flutter】FlutterKaigi2024
キャンセルします!処理を
- 呼び出す側は開始とキャンセルを要求し、呼ばれる側は開始と後始末を行い、相互に協調的に処理をすることが大切。
- Swift には Task.isCancelled と guard で対応できる。
Kotlin にも Job と CancellationException で対応できる。
Dart には ... ハッハッハ。 - Start -> Await -> Cancel の3つに分けて用意する
- Start で id を発行してもらう
- Await で id に対応をした Job を待つ
- Cancel で id に対応した Job をキャンセルする
- キャンセルで発生する Exception は Error Tracking や Metics で監視に投げて、色々と分析に繋げよう
Flutterアプリで可用性を向上させたFeatureFlagの運用戦略とその方法
- トランクベース開発で進めていく際に FeatureFlag によって、中途半端な機能を閉じてリリースを進めていける。
- WINTICKET の Feature 層は、ConnectedScreen を用意して、ホイスティングでやってるみたい。
- Feature Toggles という記事が参考になる。WINTICKET では RemoteConfig と SharedPreferences で用途に応じて、2種類を使用している。
- Widget 自体を切り分けたい場合は FlagBuilder ( onBuilder / offBuilder ) を用意して、それで分岐させていて、ルーティングを分ける場合、auto_route の guard で対応している。
- 既存の実装やデータフローを残しながら、Flag で切り分けるようにできるとバグが生まれにくい。
- actions を用いて、PR 時に flag が使われている場合に warning を出す仕組みなどを入れているが、custom-lint で気付けるようにしたいとのこと。
実践的パッケージ戦略
- override を集めてくれるパッケージ override_pod_generator
- Domain 層に Network 層の インターフェースを持たせてた
- 各パッケージをクリーンアーキテクチャの図で示すとこうなる
アニメーションを最深まで理解してパフォーマンスを向上させる
- Implicit / Explicit Animation の2種類が存在している。
- アニメーションは単に高速でコマを描画しているにすぎない。
- Ticker
- frame を制御している
- vsync
- 画面のリフレッシュレートに応じて描写する
- SingleTickerProviderStateMixin
- Widget tree が有効な場合に、その Ticker を更新してくれるやつ
- PerformanceView を用いて、どれだけ重たいかを計測する(ただし、Profile Mode で実行すること)。
- AnimatedController の個数を減らす(不要に分かれているなら、一括で管理する)。
metrics が高い部分があれば、 RepaintBoundary を用いて、再描写する範囲を抑える(ただし、AnimatedBuilder を使用したり、Component にしたりしても解決できない場合のみに留めておく)。
OS 標準のデザインシステムを超えて - より柔軟な Flutter テーマ管理
- MaterialApp / CupertinoApp は内部で持っているものが異なるが、Material 側は Cupertino を内包しているため、いじいじすることは可能になっている。
- CupertinoApp では AnimatedTheme を内部で有していないので、自分で追加するデメリットがある。
- Theme 反映の優先度は Widget > Theme.of(context) > App への設定 の順で優先される。
- Theme や MaterialApp で Widget を wrap することで、当該 tree 配下に適用させることができる。
- InheritedWidget を extends して カスタムテーマを作成することができるので、M3 から逃れたい場合に作成してみるのもありかもしれない。
- ThemeExtension を作成して適用するのもあり。
- theme_tailor は build_runner で動かせる。
- thema は登壇者が mscros を組んでるパッケージ。
- Pakcage に任せる方法もあり。
Flutterと難読化
- 難読化を行うことで、リバースエンジニアリングを困難にし、 副次的にバイナリサイズを小さくできる。
- Flutter において、 release build では基本的に難読化がされる。
- flutter build には 「obfuscate」という難読化のオプションが存在するが、単体実行は不可能で 「split-debug-info」 というシンボルファイル(flutter symbolize -d [path] を実行するときに使用するファイル)を吐き出すオプションと併用する必要がある。
- 「extre-gen-snapshot-options」を使用することで難読化のmapファイルを手に入れることができる。
- JIT / AOT が存在するが、難読化のサポートは後者のみ(Android においては、Dart の難読化の後に R8 も実行がされている)。
- web の場合は難読化ではなく、ミニファイされる。
- 「@pragma("vm:entry-point")」を付与することで難読化から除外させることができる。
マッチングアプリ『Omiai 』のFlutterへのリプレイスの挑戦
- Add to Appで逆にネイティブからモジュールとして呼び出す形でリプレイスを進めている。
- app -> domain -> repository -> system で依存しているみたい(他 base_ui などはある)。
- RepositoryResult という sealed クラスを用意して、success / failure のクラスを switch で返すようにして、全体的に全部同じように記載できるような工夫がしてあり、スニペット化もしやすいようにしてある。
- どうやら 3rd party ライブラリは system に全部入ってそう(system_hoge みたいには分けてなさそう)で、インターフェースもここのパッケージに入っていて、 app からの注入ではなさそう。
- model パッケージは独立して作られてなさそうで、それぞれのパッケージ内に定義されてそう。
- actions の matrix を組んで melos で並列してテストを回している。
- public_member_api_docs の lint ルールを ON にして、ドキュメント100% を目指している。
Effective Form ~ Flutterによる複雑なフォーム開発の実践 ~
- dirty 管理:変更が確定されたタイミングで、pure / dirty 状態になったとみなして、バリデーションを任意のタイミングで返却する。
- onChanged では pure で対応しつつも、onSubmitted では dirty で対応し、 errorText へ displayError に引っかかるようなら表示させる(← あくまで理想論)。
- 現実は管理すべき状態も多く、動的制御も必要で、依存も複雑になっている。
- Form 種別ごとに Component (app_state)を用意し、各入力種別ごとにも Component (ephemeral_state)を用意している。
作成者以外のコメントは許可されていません