一起看 I/O | Jetpack 组件的新特性

作者 / Amanda Alexander, Product Manager, Android

Android Jetpack 是开启 现代 Android 开发 (Modern Android Development,即 MAD 之门的钥匙,它是一个包含超过 100 个库、工具及指南的套件,以帮助开发者遵循最佳实践、减少模板代码,以及编写在不同 Android 版本和设备上表现一致的代码,从而使您可以专注于在应用中实现独特的功能。

在 Google Play 中,绝大多数应用都使用了 Jetpack 实现应用架构。今天,在排名前 1,000 的应用中,超过 90% 使用了 Jetpack

本文是 Jetpack 近期更新中的重点部分,也是 I/O 大会演讲: Jetpack 的新功能的延展阅读!

△ Jetpack 的新功能

接下来,我们将会介绍 Jetpack 在三个主要领域的更新:

  1. 架构库及指南;
  2. 应用的性能优化;
  3. 用户界面库及指南。

以及对一些其他关键更新的总结。

1. 架构库及指南

应用架构库及其组件可以保证应用的健壮性、可测试性,以及可维护性。

数据持久化

Room 是我们推荐的数据持久化层,它在 SQLite 之上提供了一个抽象层,从而提高了平台的可用性和安全性。

在 Room 2.4 中,对 Kotlin Symbol Processing (KSP) 的支持已经稳定。在我们针对 Kotlin 代码的基准测试中,KSP 相对 KAPT 有两倍的速度提升。Room 2.4 还内建了对枚举和 RxJava3 的支持,同时也全面支持 Kotlin 1.6。

我们从 Room 2.5 开始使用 Kotlin 对整个库进行重写。这一改变可以为未来与 Kotlin 相关的改进打下基础,同时又与之前使用 Java 编程语言编写的版本二进制兼容。这一版本还内建了对 Paging 3.0 的支持,通过使用 room-paging 组件,可以使 Room 返回 PagingSource 对象。除此之外,由于 Room 支持使用多重映射 (嵌套的 Map 和 Array) 进行关联查找,开发者现在可以使用 JOIN 查询,而无需定义额外的数据结构。

@Query("SELECT * FROM Artist 
    JOIN Song ON Artist.artistName = 
    Song.songArtistName")
fun getArtistToSongs(): Map<Artist, List<Song>>

△ 使用多重映射作为返回值的关联查找方法

AutoMigrations 在更新中加入了对额外注解和属性的支持,从而进一步简化了数据库迁移。其中,@Database 注解新加入了一个属性,可以用于定义需要在哪两个版本间进行自动迁移。而当 Room 需要一些额外信息 (如表或列的修改信息) 时,可以使用 @AutoMigration 注解指定输入。

Database(
  version = MyDb.LATEST_VERSION,
  autoMigrations = {
    @AutoMigration(from = 1, to = 2,
      spec = MyDb.MyMigration.class),
    @AutoMigration(from = 2, to = 3)
  }
)
public abstract class MyDb
    extends RoomDatabase {
  ...

DataStore

DataStore 库是一款健壮可靠的数据存储解决方案,它解决了 SharedPreferences 所存在的问题。如果想要了解如何在各种 SharedPreferences 的应用场景中使用这一强大的替代方案,您可以查看 MAD Skills: DataStore 系列文章和视频,其中包含了如何测试应用中 DataStore 库的使用情况、如何配合依赖注入使用 DataStore,以及如何从 SharedPreference 迁移至 Proto DataStore。

增量数据获取

Paging 库可以让您加载和显示整体数据中的一小部分,从而改善网络与系统资源的消耗。您可以配合 RecyclerViews 或 Compose lazy list 优雅地渐进加载应用数据。

Paging 3.1 为 Rx 和 Guava 集成提供了稳定支持,从而为 Paging 原生使用的 Kotlin 协程提供了 Java 版的替代方案。此版本还通过新的返回类型 LoadResult.Invalid 表示无效或过期的数据,从而改进了对无效竞争条件的处理。同时,该版本还通过新的 onPagesPresented 与 addOnPagesUpdatedListener API 改进了对无操作加载和操作空页面的处理。

如需了解有关 Paging 3 的更多信息,请参阅 Android 开发者网站中全新简化版的教程: Paging Basics Codelab,它描述了如何在包含列表的应用中集成 Paging 库。

定义应用内导航模型

Navigation 库是用于在应用中的目的地之间进行移动的框架。

Navigation 组件现已通过 navigation-compose 组件集成到了 Jetpack Compose 中,从而允许可组合函数作为您应用中的目的地。

经过优化的 Multiple Back Stacks 功能,更便于 Navigation 组件记录状态。NavigationUI 现在可以自动存储和恢复弹出目的地的状态,这意味着开发人员无需改动任何代码即可支持多返回栈。

Navigation-fragment 组件进一步增强了对大屏幕设备的支持,它在 AbstractListDetailFragment 中提供了一个预制的双窗格布局实现。这一 Fragment 使用 SlidingPaneLayout 管理一个列表窗格 (由您的子类管理),以及一个由 NavHostFragment 实现的详情窗格。

所有的 Navigation 组件现已使用 Kotlin 重写,并使用泛型改进了类的可空性,例如 NavType 的子类。

架构库指南

针对我们的核心架构库如何协同使用这一问题,如您想要了解更多信息,可以观看我们的视频与 文章 合集,这其中涵盖了现代 Android 开发最佳实践系列内容——MAD Skills: 架构

2. 优化应用性能

通过使用性能库,您可以构建高性能的应用,并作出针对性的优化以维持其性能表现,从而获得更好的终端用户体验。

优化启动时间

应用的启动时间对用户体验影响巨大,特别是在应用安装完成后立即使用时尤为明显。为了提升首次启动时的体验,我们创建了 Baseline Profiles。Baseline Profiles 允许应用和库向 Android 运行时提供有关代码路径使用情况的元数据,从而确定提前编译的优先级。这一配置文件会对依赖库的数据进行聚合,以 baseline.prof 文件的形式放入应用的 APK 中,并且随后会在安装时用于实现应用的部分预编译以及用于静态链接库代码中。这会使您的应用加载的更快,并且可以在用户首次与应用交互时减少丢帧。

我们已经开始在 Google 内部使用 Baseline Profiles。Play Store 应用在接入 Baseline Profiles 后,搜索结果页初始页面的渲染时间减少了 40%。为了给终端用户提供更好的用户体验,一些流行的依赖库也已经加入了 Baseline Profiles,例如 Fragment 和 Compose。如果想要创建您自己的基线配置文件,您需要使用 Macrobenchmark 库。

检测您的应用

Macrobenchmark 库可以通过将 Jetpack 基准测试的覆盖范围扩展至更为复杂的用例,来帮助开发者更好的了解应用性能。这其中包含了应用启动及集成界面操作 (如滚动 RecyclerView 或运行动画)。Macrobenchmark 也可用于生成 Baseline Profiles。

Macrobenchmark 已经更新以提高测试速度,同时也带来了几个新的实验性功能。它现在还支持通过使用 TraceSectionMetric 进行基于自定义跟踪的时序测量,从而允许开发者针对特定的代码部分进行基准测试。此外,AudioUnderrunMetric 现在可以检测音频缓存欠载,以帮助开发者了解音频卡顿的情况。

BaselineProfileRule 可以生成配置文件来帮助进行运行时优化。它的工作方式与其他宏基准测试类似,您只需通过 lambda 代码表示用户操作即可。在下面的示例中,编译器应该提前优化的关键用户场景是冷启动: 从启动器打开应用的启动 Activity。

@ExperimentalBaselineProfilesApi
@RunWith(AndroidJUnit4::class)
class BaselineProfileGenerator {
  @get:Rule
  val baselineProfileRule = BaselineProfileRule()

  @Test
  fun startup() = baselineProfileRule.collectBaselineProfile(
    packageName = "com.example.app"
  ) {
    pressHome()

    // 这一代码块定义了应用的关键用户场景。这里我们所关注的是应用启动的优化,但您
    // 也可以进行导航和滚动浏览您最重要的界面。
    startActivityAndWait()
  }
}

如需了解更多关于通过 Macrobenchmark 生成和使用基准配置文件的详细信息和完整指南,请参阅 Android 开发者的指南文档——基准配置文件

避免界面卡顿

全新的 JankStats 库可以帮您追踪和分析应用界面的性能问题,其中包括报告丢失渲染帧——通常被称为 “卡顿 (jank)”。JankStats 建立在现有 Android 平台 API (例如 FrameMetrics) 之上,但最低可以用于 API Level 16。

JankStats 还提供了超越平台内置功能的其他能力: 帮助定位丢帧原因的启发式算法、在报告中提供了额外上下文的界面状态,以及可以用于上传数据以进行分析的报告回调。

下面我们详细说说 JankStats 的三个主要功能:

  1. 识别卡顿 : JankStats 使用内置的启发式算法确定卡顿发生的时机,并使用该信息得知何时发布卡顿报告,从而使开发者可以获得有关这些问题的信息,以帮助分析和修复问题。

  2. 提供界面上下文 : 为了提高卡顿报告的可利用性和可操作性,JankStats 提供了一个帮助追踪当前界面和用户状态的机制。每当记录报告时,都会提供相应的信息,这样不但可以帮助开发者了解问题是何时发生的,更可以了解到用户当时在做什么。这有助于确定应用中存在问题的区域,以便稍后进行解决。这其中一些状态是由一些 Jetpack 库自动提供的,但我们也鼓励开发者提供自己应用特定的状态。

  3. 报告结果 : 在每一帧中,JankStats 客户端都会通过监听器收到包含该帧相关信息的通知,包括帧完成所用的时间、是否被视为卡顿,以及该帧显示期间的界面上下文是什么。我们鼓励客户端聚合和上传适合分析的数据,以帮助和调试整体性能问题。

在您的应用中添加日志

Tracing 库通过将跟踪事件写入系统缓冲区来启用应用性能分析。Tracing 1.1 支持对低至 API Level 14 的应用的非调试构建进行分析,类似于在 API Level 29 中加入的 清单文件标记。

3. 界面库及指南

我们对界面库进行了一些更改,以更好地支持大屏幕兼容性、可折叠设备和 Emoji。

Jetpack Compose

Jetpack Compose 是 Android 用于构建原生界面的现代工具,如今已更新至 1.2 beta 版。新版本添加了一些用于支持先进用例的功能,包括支持可下载字体、惰性布局及嵌套滚动互操作性。更多信息请参阅文章: 一起看 I/O | Jetpack Compose 中的新特性

了解窗口状态

新的 WindowManager 库通过提供一个支持低至 API Level 14 的通用 API 界面,帮助开发人员适配他们的应用支持多窗口环境和新的设备形态。

最初的版本针对可折叠设备的用例,包括查询影响内容显示方式的物理属性。

Jetpack 的 SlidingPaneLayout 组件已更新为使用 WindowManager 的智能布局 API,以避免内容被放置于被遮挡区域 (例如跨越物理铰链区域)。

拖放

新的 DragAndDrop 通过让开发者接收来自应用内外的拖放数据,来帮助在新的外形和窗口模式下实现功能。DrapAndDrop 包含了一致的放置目标功能,它最低支持 API Level 24:

移植新 API 到旧的 API Level

AppCompat 库可以让我们在旧平台 API 版本下访问新的 API,包含一些界面功能移植,如暗色模式。

AppCompat 1.4 集成了 Emoji2 库,从而为 API Level 14 及以上版本、AppCompat 中支持的所有基于文本的视图带来了对新 Emoji 的默认支持。

自定义区域选择 目前已支持低至 API Level 14。该功能支持跨应用手动持久化区域设置,并且可以通过 Service 的 metadata 标签支持自动持久化。它可以告诉库同步加载区域并根据需要重建任何正在运行的 Activity。在 API Level 33 及以上,持久化是由平台管理的,无需额外开销。

其他关键更新

Annotation

Annotation 库公开了元数据,从而帮助工具和其他开发者理解应用的代码。它提供了一些我们耳熟能详的注解,如 @NonNull。这些注解与 lint 检查配对,可以提高代码的正确性和可用性。

Annotation 正迁移至 Kotlin,所以正使用 Kotlin 的开发者会看到更合适的注解目标,包括 @file

一些呼声很高的注解已随其相应的 lint 检查添加了进来。其中包括了有关方法或函数重写的注解,以及 @DeprecatedSinceApi 注解。后者作为 @RequiresApi 的必然结果,可以阻止在某个 API 级别之上进行使用。

在 Github 上为 Jetpack 代码仓库做贡献

我们目前在 GitHub 上已有超过 100 个项目

开发者可以向下列项目贡献代码,它们均基于 Github 的标准流程:

  • Activity
  • AppCompat
  • Biometric
  • Collection
  • Compose Compiler
  • Compose Runtime
  • Core
  • DataStore
  • Fragment
  • Lifecycle
  • Navigation
  • Paging
  • Room
  • WorkManager

查看 项目主页 可获得更多内容,包括我们如何处理拉取请求,以及如何开始使用 Jetpack 构建应用。

以上就是对过去几个月 Jetpack 所有变更的简要介绍。更多有关每个 Jetpack 库的信息,请参阅以下资料:

欢迎您 点击这里 向我们提交反馈,或分享您喜欢的内容、发现的问题。您的反馈对我们非常重要,感谢您的支持!

*Java 是 Oracle 和/或其附属公司的商标或注册商标