DroidKaigi day1
Gradle Convention Plugins
Gradle Convention Pluginsを使用すると、特にAndroidアプリ開発者にとって共通設定をモジュール全体に簡単にかつ効果的に適用できます。Convention pluginsには、build scriptの共通化以上にビルドフェーズでの利点があります。一方で、誤った実装/構成は、構成キャッシュ(configuration cache)などGradleのビルド機能に悪影響を及ぼす可能性があるため、利点を得るにはプラグインを*正しく*実装する必要があります。
このセッションでは、Android開発者がGradle Convention Pluginを知っておくべき理由を説明した後、Gradle pluginを一から作る方法と、Android Gradle Pluginと連携するpluginのいくつかの例を見せます。
Effective Convention Plugins
Gradle Build Lifecycle
- Initialization
- Configuration
- Execution
Composite Builds with build cache, Reuse outputs to classpath
buildSrc with Gradle 7 and lower not reccommended
Plugin Writing
具体的にどう書いたら良いか
Lazy Provider API というのがある
Abstract Task を拡張して書ける
まとめ
- Gradle 8 以上を利用して、その効能を享受しよう!
- 共通ロジック間では、 Gradle Convetion Plugins を使おう
- 常にキャッシュを気にするのはベストプラクティスだということを忘れないで!
会場でも利用している Android Studio のバージョンは分散している
バージョンごとではなく、機能中心でお話しする
- UI Tools for coding
- Build system
- App Inspection
ここにメモするのは、 Giraffe ベース
IntelliJ の新機能
- 新しいUIテーマをサポート
- 機能が肥大化しているので、初学者向けに情報を絞る
- Eclipse っぽさがある
- macOS Metal API 利用で速くなっている
- AGP と Gradle のバージョンが揃っているので合わせるようにする
UI Tools
- Live Edit が Composable に対応( hot reload like Flutter
- Hedgehog から Compose Multipreview templates が増えてる
- Compose Animation Preview Extend animation に対応
- HedgeHog から Firebase Test Lab devices with Gradle Managed Devices
- AGP 8.2.0-alpha03以降から
Build
- Giraffe で起動可能なプロジェクト
- Giraffe で扱える最新ビルド環境に更新したプロジェクト
Giraffe なら Gradle 8.1, AGP 8.1
Compose Runtime ライブラリ
ビルド時間を計測する Build Analyzer
- Download impact in Build Analyzer
- キャッシュのススメ
- Build Analyzer task categorization
- Build のどのタスクで時間がかかっているかカテゴライズしてくれる
- 重い plugin を探すこともできる
- Gradle sync でのダウンロード統計
- 依存関係が可視化される
- Android SDK Upgrade Assistant
- やる回数は多いのでテンプレートに頼る
- Gradle Build Script Kotlin DSL
- Google recommend
- 同一言語
- Gradle Version Catalog
- マルチモジュールやプロジェクト間で依存関係を共有できる
- Giraffe は Experimental, Hedgehog は stable
Inspect
品質を担保するための行い
- Network Inspector traffic
- 書き換えも可能
- App Quality Insights
- IDE から直接 Firebase Crashlytics レポートを確認できる
- Notes も書ける
- ジャンプできる
- コードハイライトできる
- Git バージョンとの同期は?
- Hedgehog から Android vitals 対応
- Android Studio でログインが必要
- Iguana からバージョン管理システムを統合(ここで Git と連携する
- Android Studio bot がバグを修正する日も近い
- 少なくとも PR や issue 立てとして、このコードはまずいとレビューコメントは自動生成してくれそう
- Compose トレース対応
- recompose されているかを Compose 関数を把握できる
- Hedgehog からデバッグ中の Compose state 情報表示
- Iguana から Test against configuration changes with the Espresso Device API
- Espresso Device API を追加して対応する
- 仮想デバイス上でシミュレートしてテストする
移行計画
- Nightly がある
- Android Studio は3ヶ月ごとのリリースサイクルを維持されている
- チームの生産性と複雑性を見極めて判断する
- 後半に行くほど影響範囲が大きい
(Unofficial) Guide to Architecture Guide Vol.2
去年の Vol.1
- 依存性の注入
- Hilt は完璧ではない
- モジュールアーキテクチャ
原則を読んでいないと内容は難しいので概要だけ掴んでもらえれば
Google の人の発表だが、公式の見解ではない
Google Guide
- 全てのケースに該当するではない
- あなたのプロジェクトに何が必要なのか、ビジネスゴールを達成するのに何が必要なのか
好例
- Slack
- Circuit: MVP on Compose
- Presenter も Composable にして State で状態を更新している
- よくできているので参考になる
- Turo's architecture
- ナビゲーションの課題を解決している
- コードが綺麗
- タイプセーフ
- Fragment をラップしているので危険性はある
依存性の注入
Dagger
- DAG(Directed Acyclic Graphs)
- 循環参照の防止
なぜ Hilt?
- Google たくさん使われている
- ボイラープレートを大幅に減らせる
- Google で一番大事にしているのはテスト
- それを解決するために使われている(どう解決している?
- Hilt にも苦手なことがある
- Custom Scope
- square/anvil がこの問題を解決するのが得意
- 本来 Hilt がやるべき(笑
- Dagger の拡張
- KPT ではなく、コンパイルで解析(なので速い
- square/anvil がこの問題を解決するのが得意
- No native Kotlin support
- 元々 Java ベースなので
- Compose friendly でない要因の一つ
- state hoisting
- Custom Scope
カプセル化が崩れる
-> DI で解決できる
CompositionLocal を使えば良いのでは?
->
- nested structure で効果的に使えない
- 異なるライフサイクルに対する制御が難しい
解決方法
- Composable as a state holder
- Add custom Scope
- ViewModelScope で表現するのは難しい
マルチモジュール
- Google からの公式資料があるので読んでおくと良い
- ビルド時間
- モジュールによって Ownership を分割する
- アプリを分割しておけば問題を扱うのが楽になる
原則
- カプセル化に貢献するか
- 内部結合が発生している場合
- APIでカプセル化する
- 強い依存なら、無理にモジュールを分割しない
- モジュールごとに Owner が違う
- 組織が多くなると分割が起こる
- コンウェイの法則に従う必要はない
- 少ないメンバーでもある程度のモジュール分割は推奨される
- 単一責任の原則に従う
- モジュールの大きさは基準ではない
- モジュール分割は今すぐやろう
- モジュールを分ける労力は大変ではない
- 遅くなるほど大変になる
- 潜在的な課題が見えてくる
- カプセル化が強制される
アンチパターン
- 循環参照
- IF と実装のモジュールを分けてしまう
- 実体への依存
- 依存関係の逆転
- 上位のモジュールは下位のモジュールを import しない
- runtimeonly というのがある
- domain側への影響しない
Androidアプリ開発者として過ごす中では、UIやロジック、コードの品質、テーマに注力することが多く、Androidのブートプロセスにはあまり触れることがありません。
Androidが正規のデバイスで起動していることを保証している方法や、OEMに特化したものも含めてそれぞれのパーティションの完全性を保証するために行われている手続きの内容を知るのは楽しいことです。
Androidデバイスは様々なメーカーによって作られているため、ブート時の検証は困難を極めます。
この発表では、起動時の検証の裏側や起動のフロー、ロールバック保護、各パーティションの完全性を保証するためのハッシュと暗号キーの利用といった内容を話す予定です。
同時通訳がありがたい。内容が難しい
Android のパーテションの話から
どうやって hash を計算するか
-> Tree Hashing する
Verification sequence
- Boot 時はユーザ操作が必要
- Run time はエラーフラグを立てて再起動する
eio mode?
OTA update を考える
-> Passive / Active でフローが変わる
-> slot とは?
Verified boot 2.0 とは?
- Android 8 から
- VBMeta digst が使える
- HW Attestation
- VerifiedBootState が提供される
ネストスクロールは一つのスクロールに複数のコンポーネントが関わっている状態
JetpackCompose と AndroidView でスクロールの仕様が異なる
JetpackCompose
- Modifier に rememberScrollState を渡せば良い
- TopAppBar のscrollBehavior を適用すれば良い
- Material3 だとレイアウトのカスタムが困難
- デフォルトでネストスクロールをサポート
- 子の消費量を親に渡してくれる
- AndroidView はサポートしていない
- NestedScrollConnection が提供されている
- interface なので実装することでカスタマイズ可能
- 可変にしたい部分は State にする
AndroidView との比較
- ネストスクロールをサポートしていない
- 複雑なレイアウトだとタッチイベントの優先度に依存した挙動になる
- タッチイベントをカスタマイズすることで Compose と似たような表現は可能
- 画面の端や子のコンポーネントの計算が必要
- CoordinateLayout
- MotionLayout
- NestedScrollingPreScroll
- NestedWebView が一例
相互運用の注意点
AndroidView Compose の親子の組み合わせによって接続の仕方は異なるが、ネストスクロールの表現は可能