为了包含 Jetpack Compose 1.0.0-beta05 的更新内容,这篇文章在第一次发布后做出了更新。如果您希望查看原始版本,请参见:
https://web.archive.org/web/20210226105855/https://medium.com/androiddevelopers/jetpack-compose-before-and-after-8b43ba0b7d4f
2020 年,我开始了缓慢迁移 Tivi UI 的任务,目标是使其转为由 Jetpack Compose 编写。大约 12 个月之后,任务完成!????
Tivi
https://tivi.app/Jetpack Compose
https://developer.android.google.cn/jetpack/compose
在本文中,我们将会回顾并对比一些关键指标,以了解 Compose 相对的优势,其中包括: APK 大小、构建速度、代码行数。
应用本身
在我们进一步了解 Compose 的相关内容前,先让我快速地描述一下应用本身。
Tivi 已经高度模块化,它每个 UI 的界面都在其自身的 Gradle 模块中 (名为 ui-$NAME)。每个界面都使用 Fragment 实现,随后在主 app 模块中使用 AndroidX Navigation 将它们结合起来。为了让您对架构有一个直观印象,下面是应用的模块图:
△ Tivi 的模块图,使用 Jake Wharton 所提供的,十分方便的 Gradle 任务生成
由于导航图使用深度链接 URI 实现,大多数 Fragment 彼此之间一无所知,从而保证了解耦。或许更为重要的是,这种形式支持独立模块编译,从而有助于进行并行构建。
Fragment
https://developer.android.google.cn/guide/fragments
AndroidX Navigation
https://developer.android.google.cn/guide/navigation
Jake Wharton
https://twitter.com/JakeWhartonGradle 任务
https://github.com/JakeWharton/SdkSearch/blob/master/gradle/projectDependencyGraph.gradle深度链接 URI
https://developer.android.google.cn/guide/navigation/navigation-deep-link
注意: Tivi 的模块结构并不完美。其中,UI 模块 (位于顶层) 与基础模块 (位于底层) 间仍有许多依赖。理想情况下,每个层级应当保持分离。我接下来的工作正是要优化这一问题。
在开始迁移至 Compose 之前,Tivi 已经使用了 Android 开发者可以使用的所有炫酷 UI 组件,包括但不限于: Data Binding、Epoxy、Material Design Components、Insetter DBX、MotionLayout。但不幸的是,其中的许多组件使用了注解处理,因而也带来了额外的构建消耗。
Data Binding
https://developer.android.google.cn/topic/libraries/data-bindingEpoxy
https://github.com/airbnb/epoxyMaterial Design Components
http://material.io/develop/android/Insetter DBX
https://github.com/chrisbanes/insetterMotionLayout
https://developer.android.google.cn/training/constraint-layout/motionlayout
迁移流程
前面我曾提到,我们已经完成了迁移的 "第一幕",这话是什么意思呢?现在的应用看起来与我在 2020 年二月开始迁移时别无二致。
应用的模块化意味它可以分片完成迁移,每次只用迁移一个 Fragment——而这也是近 11 个月以来 46 个拉取请求中所做的事。
46 个拉取请求
https://github.com/chrisbanes/tivi/pulls?q=compose
我从一个简单的界面: 剧集详情开始迁移,接下来是演出详情、"发现"、"搜索"、"关注的演出" 等等。最近在 Paging3 支持了 Compose 后,我迁移了最后的界面: "列表" 网格: