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

DroidKaigi 2022のカンファレンスアプリを眺める

DroidKaigi 2022のカンファレンスアプリを眺める

Mikami Hiroki

March 31, 2023
Tweet

More Decks by Mikami Hiroki

Other Decks in Programming

Transcript

  1. <<
    DroidKaigi 2022
    カンファレンスアプリを
    眺める
    DroidKaigi.collect{ #[email protected] }

    View Slide

  2. ● 株式会社ゆめみ(Androidエンジニア)
    ● Twitter: @mono33__
    みかみ

    View Slide

  3. カンファレンスアプリを眺め
    気になるトピックを2つ深堀

    View Slide

  4. アジェンダ
    1. カンファレンスアプリについて
    2. カンファレンスアプリを眺める
    3. 感想

    View Slide

  5. アジェンダ
    1. カンファレンスアプリについて
    2. カンファレンスアプリを眺める
    3. 感想

    View Slide

  6. カンファレンスアプリの概要
    ● イベント当日に重宝するアプリ
    ○ セッションのスケジュール確認や管理、
    会場マップの表示などの機能
    ● 毎年多くのエンジニアによってOSS開発
    ○ 今年は約150名ほど

    View Slide

  7. カンファレンスアプリの技術特徴
    ● モダンな技術要素
    ○ Jetpack ComposeやFlow、Compose Material 3
    ● 挑戦的な要素
    ○ Kotlin Multiplatform[1]
    ■ iOSまでもリリース
    [1] Kotlin Multiplatform, https://kotlinlang.org/docs/multiplatform.html

    View Slide

  8. View Slide

  9. アジェンダ
    1. カンファレンスアプリについて
    2. カンファレンスアプリを眺める
    3. 感想

    View Slide

  10. ビルドロジック

    View Slide

  11. [2] Tech Stacks, https://github.com/DroidKaigi/conference-app-2022

    View Slide

  12. モジュール構成
    Now in Android をベースにした
    マルチモジュール構成
    app, feature, core が主
    benchmarkやpreview-screenshots
    iOS関連のものも

    View Slide

  13. モジュール構成
    Now in Android をベースにした
    マルチモジュール構成
    app, feature, core が主
    benchmarkやpreview-screenshots,
    iOS関連のものも

    View Slide

  14. 増えるボイラープレート
    スケーラビリティや再利用性の点でメリットがあるが、
    モジュールが多いとGradleの記述・管理が大変に
    モジュール数が
    多いほど記述が
    増える

    View Slide

  15. マルチモジュールの注意点
    スケーラビリティや再利用性の点でメリットがあるが、
    モジュールが多いとGradleの記述が大変に
    モジュール数が
    多いほど記述が
    増える
    効率的にビルドスクリプトを
    管理したい🤔

    View Slide

  16. ビルドスクリプトの一元化
    ● ビルドスクリプトを一元化してボイラープレートを
    削減
    ● buildSrcはいくつかの問題点[3]
    ○ ビルド毎に不必要なタスクが実行されてしまう
    ○ buildSrcに変更があった場合再構築される
    [3] Herding Elephants, https://developer.squareup.com/blog/herding-elephants/

    View Slide

  17. build-logic の登場
    ● Version Catalog[4]とComposite Build[5]の組み合わせ
    build-logicを作る
    ● Now in Android[6] でも採用
    [4] Sharing dependency versions between projects, https://docs.gradle.org/current/userguide/platforms.html
    [5] Composing builds, https://docs.gradle.org/current/userguide/composite_builds.html
    [6] Now in Android, https://github.com/android/nowinandroid

    View Slide

  18. [7] https://github.com/DroidKaigi/conference-app-2022/tree/main/gradle

    View Slide

  19. @Suppress("unused")
    class AndroidPlugin : Plugin {
    override fun apply(target: Project) {
    with(target) {
    with(pluginManager) {
    apply("com.android.library")
    }
    androidLibrary {
    setupAndroid()
    }
    }
    }
    }
    primitive
    @Suppress("unused")
    class AndroidKotlinPlugin : Plugin {
    override fun apply(target: Project) {
    with(target) {
    with(pluginManager) {
    apply("org.jetbrains.kotlin.android")
    }
    android { /* ... */}
    }
    }
    }
    }

    View Slide

  20. @Suppress("unused")
    class AndroidPlugin : Plugin {
    override fun apply(target: Project) {
    with(target) {
    with(pluginManager) {
    apply("com.android.library")
    }
    androidLibrary {
    setupAndroid()
    }
    }
    }
    }
    primitive
    @Suppress("unused")
    class AndroidKotlinPlugin : Plugin {
    override fun apply(target: Project) {
    with(target) {
    with(pluginManager) {
    apply("org.jetbrains.kotlin.android")
    }
    android { /* ... */}
    }
    }
    }
    }

    View Slide

  21. build-logicのbuild.gradle.kts
    gradlePlugin {
    plugins {
    // Primitives
    register("android") {
    id = "droidkaigi.primitive.android"
    implementationClass = "io.github.droidkaigi.confsched2022.primitive.AndroidPlugin"
    }
    register("androidKotlin") {
    id = "droidkaigi.primitive.android.kotlin"
    implementationClass = "io.github.droidkaigi.confsched2022.primitive.AndroidKotlinPlugin"
    }
    }
    }

    View Slide

  22. convention
    class AndroidFeaturePlugin : Plugin {
    override fun apply(target: Project) {
    with(target) {
    with(pluginManager) {
    apply("droidkaigi.primitive.android")
    apply("droidkaigi.primitive.android.kotlin")
    apply("droidkaigi.primitive.android.compose")
    /* ... */
    }
    }
    }
    }

    View Slide

  23. convention
    class AndroidFeaturePlugin : Plugin {
    override fun apply(target: Project) {
    with(target) {
    with(pluginManager) {
    apply("droidkaigi.primitive.android")
    apply("droidkaigi.primitive.android.kotlin")
    apply("droidkaigi.primitive.android.compose")
    /* ... */
    }
    }
    }
    }

    View Slide

  24. build-logicのbuild.gradle.kts
    gradlePlugin {
    plugins {
    // Primitives
    /* ... */
    // Conventions
    register("androidFeature") {
    id = "droidkaigi.convention.androidfeature"
    implementationClass = "io.github.droidkaigi.confsched2022.convention.AndroidFeaturePlugin"
    }
    register("kmp") {
    id = "droidkaigi.convention.kmp"
    implementationClass = "io.github.droidkaigi.confsched2022.convention.KmpPlugin"
    }
    }
    }

    View Slide

  25. プロジェクト配下のsettings.gradle.kts
    pluginManagement {
    includeBuild("gradle/build-logic")
    repositories {
    gradlePluginPortal()
    google()
    mavenCentral()
    }
    }

    View Slide

  26. build.gradle.kts
    plugins {
    id("droidkaigi.convention.androidfeature")
    }
    android.namespace = "io.github.droidkaigi.confsched2022.feature.about"
    dependencies {
    /* ... */
    }

    View Slide

  27. Single source of truth for your build scripts
    [7] Single source of truth for your build scripts,
    https://proandroiddev.com/single-source-of-truth-for-your-build-scripts-72d584534949

    View Slide

  28. ビルド周りについての所感
    ● Version Catalogはクセはあるが...
    ○ Renovateに続きDependabotの依存関係自動更新対応[8]
    ● build logic は色々な難しい
    ● Gradle 8.0.xのアップデート[9]
    ○ buildSrcのincludeBuild対応をはじめとして
    パフォーマンス周りで改善
    ● 今後まだまだ変更があるかも🤔
    [8] Dependabot version updates keeps Gradle version catalogs up-to-date
    [9] Gradle Release Notes, https://docs.gradle.org/current/release-notes.html

    View Slide

  29. appモジュールとCompose

    View Slide

  30. View Slide

  31. 結合を低く保つ
    [10] Common modularization patterns, https://developer.android.com/topic/modularization/patterns#communication

    View Slide

  32. @AndroidEntryPoint
    class MainActivity : AppCompatActivity() {
    /* ... */
    override fun onCreate(savedInstanceState: Bundle?) {
    /* ... */
    setContent {
    KaigiApp(
    windowSizeClass = calculateWindowSizeClass(this),
    sessionIdFromNotification = sessionIdString
    )
    }
    }
    /* ... */
    } :app-android

    View Slide

  33. @Composable
    fun KaigiApp(/* ... */) {
    KaigiTheme(/* ... */) {
    KaigiAppDrawer(/* ... */) {
    NavHost(
    modifier = Modifier,
    navController = kaigiAppScaffoldState.navController,
    startDestination = SessionsNavGraph.sessionRoute,
    ) {
    sessionsNavGraph(/* ... */)
    contributorsNavGraph(/* ... */)
    aboutNavGraph(/* ... */)
    /* ... */
    }
    }
    }
    } :app-android

    View Slide

  34. @Composable
    fun KaigiApp(/* ... */) {
    KaigiTheme(/* ... */) {
    KaigiAppDrawer(/* ... */) {
    NavHost(
    modifier = Modifier,
    navController = kaigiAppScaffoldState.navController,
    startDestination = SessionsNavGraph.sessionRoute,
    ) {
    sessionsNavGraph(/* ... */)
    contributorsNavGraph(/* ... */)
    aboutNavGraph(/* ... */)
    /* ... */
    }
    }
    }
    } :app-android

    View Slide

  35. @Composable
    fun KaigiApp(/* ... */) {
    KaigiTheme(/* ... */) {
    KaigiAppDrawer(/* ... */) {
    NavHost(
    modifier = Modifier,
    navController = kaigiAppScaffoldState.navController,
    startDestination = SessionsNavGraph.sessionRoute,
    ) {
    sessionsNavGraph(/* ... */)
    contributorsNavGraph(/* ... */)
    aboutNavGraph(/* ... */)
    /* ... */
    }
    }
    }
    } :app-android

    View Slide

  36. fun NavGraphBuilder.aboutNavGraph(
    onStaffListClick: () -> Unit,
    /* ... */
    ) {
    composable(route = AboutNavGraph.aboutRoute) {
    AboutScreenRoot(
    onStaffListClick = onStaffListClick,
    /* ... */
    )
    }
    } :feature:about

    View Slide

  37. fun NavGraphBuilder.aboutNavGraph(
    onStaffListClick: () -> Unit,
    /* ... */
    ) {
    composable(route = AboutNavGraph.aboutRoute) {
    AboutScreenRoot(
    onStaffListClick = onStaffListClick,
    /* ... */
    )
    }
    } :feature:about
    fun onStaffListClick() {
    navController
    .navigate(
    StaffNavGraph.staffRoute,
    )
    }
    :app-android

    View Slide

  38. fun NavGraphBuilder.aboutNavGraph(
    onStaffListClick: () -> Unit,
    /* ... */
    ) {
    composable(route = AboutNavGraph.aboutRoute) {
    AboutScreenRoot(
    onStaffListClick = onStaffListClick,
    /* ... */
    )
    }
    } :feature:about
    fun onStaffListClick() {
    navController
    .navigate(
    StaffNavGraph.staffRoute,
    )
    }
    :app-android

    View Slide

  39. @Composable
    fun KaigiApp(/* ... */) {
    KaigiTheme(/* ... */) {
    KaigiAppDrawer(/* ... */) {
    NavHost(
    modifier = Modifier,
    navController = kaigiAppScaffoldState.navController,
    startDestination = SessionsNavGraph.sessionRoute,
    ) {
    sessionsNavGraph(/* ... */)
    contributorsNavGraph(/* ... */)
    aboutNavGraph(/* ... */)
    /* ... */
    }
    }
    }
    } :app-android

    View Slide

  40. @Composable
    fun KaigiApp(/* ... */) {
    KaigiTheme(/* ... */) {
    KaigiAppDrawer(/* ... */) {
    NavHost(
    modifier = Modifier,
    navController = kaigiAppScaffoldState.navController,
    startDestination = SessionsNavGraph.sessionRoute,
    ) {
    sessionsNavGraph(/* ... */)
    contributorsNavGraph(/* ... */)
    aboutNavGraph(/* ... */)
    /* ... */
    }
    }
    }
    } :app-android

    View Slide

  41. Composeにおける制限
    ● 子のComposableの領域は親の
    Composableの領域以下
    ○ Scaffoldの中から全画面に
    ModalBottomSheetを呼び出すと
    全画面に表示できない

    View Slide

  42. Composeにおける制限
    ● 子のComposeの生存期間
    ○ Snackbarを子Composableで呼び出すと
    子のComposableと共に消えてしまうことがある

    View Slide

  43. まとめると...
    ● appモジュール
    ○ それぞれのfeatureモジュールへの参照をもつ
    ○ DrawerやScaffoldやThemeなどアプリ全体に関わるも

    ● featureモジュール
    ○ appモジュールにNavGraphを公開
    ○ appモジュールで実装されている遷移実装の呼び出し

    View Slide

  44. アジェンダ
    1. カンファレンスアプリについて
    2. カンファレンスアプリを眺める
    3. 感想

    View Slide

  45. 2021年のカンファレンスアプリと比較して
    ● Jetpack Composeは継続
    ○ Accompanist[11]も含めて開発が進んでいる
    ● Compose Material 3[12]が登場 & 実装にも
    ● 全体的に実装の方針が定まりつつある印象
    ○ Google公式のドキュメントの充実
    ○ Now in AndroidなどのOSSプロジェクト
    [11] Accompanist, https://google.github.io/accompanist/
    [12] Compose Material 3, https://developer.android.com/jetpack/androidx/releases/compose-material3

    View Slide

  46. めちゃくちゃ勉強に
    なりました!

    View Slide

  47. 来年度もAndroid & DroidKaigi
    やっていきましょう🙌

    View Slide

  48. CREDITS: This presentation template
    was created by Slidesgo, including
    icons by Flaticon, infographics &
    images by Freepik.
    Thanks!

    View Slide

  49. References 1
    ● [1] Kotlin Multiplatform, https://kotlinlang.org/docs/multiplatform.html
    ● [2] Tech Stacks, https://github.com/DroidKaigi/conference-app-2022
    ● [3] Herding Elephants, https://developer.squareup.com/blog/herding-elephants/
    ● [4] Sharing dependency versions between projects,
    https://docs.gradle.org/current/userguide/platforms.html
    ● [5] Composing builds, https://docs.gradle.org/current/userguide/composite_builds.html
    ● [6] Single source of truth for your build scripts,
    https://proandroiddev.com/single-source-of-truth-for-your-build-scripts-72d584534949
    ● [7] Single source of truth for your build scripts,
    https://proandroiddev.com/single-source-of-truth-for-your-build-scripts-72d584534949

    View Slide

  50. References 2
    ● [8] Dependabot version updates keeps Gradle version catalogs up-to-date,
    https://github.blog/changelog/2023-03-13-dependabot-version-updates-keeps-gradle-version-cata
    logs-up-to-date/
    ● [9] Gradle Release Notes, https://docs.gradle.org/current/release-notes.html
    ● [10] Common modularization patterns,
    https://developer.android.com/topic/modularization/patterns#communication
    ● [11] Accompanist, https://google.github.io/accompanist/
    ● [12] Compose Material 3,
    https://developer.android.com/jetpack/androidx/releases/compose-material3

    View Slide