使用 Firebase 和 Jetpack Compose 构建 Android 应用

一、简介

最后更新: 2022-11-16

使用 Firebase 和 Jetpack Compose 构建 Android 应用

在此 Codelab 中,您将构建一个名为Make It So的 Android 应用。该应用程序的 UI 完全使用Jetpack Compose构建,Jetpack Compose 是 Android 用于构建本机 UI 的现代工具包 - 它非常直观,并且比编写 .xml 文件并将其绑定到 Activity、Fragment 或 View 所需的代码更少。

了解 Firebase 和 Jetpack Compose 如何协同工作的第一步是了解现代 Android 架构。良好的架构使系统易于理解、易于开发和维护,因为它使组件的组织方式和相互通信的方式变得非常清晰。在 Android 世界中,推荐的架构称为Model - View - ViewModel模型代表访问应用程序中数据的层。 View是 UI 层,不应该了解业务逻辑。而ViewModel是业务逻辑应用的地方,有时需要ViewModel调用Model层。

我们强烈建议您阅读本文,了解如何将模型 - 视图 - ViewModel应用于使用 Jetpack Compose 构建的 Android 应用程序,因为这将使代码库更易于理解,后续步骤也更容易完成。

你将构建什么

Make It So是一个简单的待办事项列表应用程序,允许用户添加和编辑任务、添加标志、优先级和截止日期,并将任务标记为已完成。下图显示了该应用程序的两个主页:任务创建页面和包含已创建任务列表的主页。

让它如此 添加任务屏幕让它如此主屏幕

您将添加此应用程序中缺少的一些功能:

  • 使用电子邮件和密码对用户进行身份验证
  • 向 Firestore 集合添加侦听器并使 UI 对更改做出反应
  • 添加自定义跟踪以监控应用程序中特定代码的性能
  • 使用远程配置创建功能切换并使用分阶段推出来启动它

你将学到什么

  • 如何在现代 Android 应用程序中使用 Firebase 身份验证、性能监控、远程配置和 Cloud Firestore
  • 如何使 Firebase API 适合 MVVM 架构
  • 如何在 Compose UI 中反映使用 Firebase API 所做的更改

你需要什么

2. 获取示例应用并设置 Firebase

获取示例应用程序的代码

从命令行克隆 GitHub 存储库:

git clone https://github.com/FirebaseExtended/make-it-so-android.git

设置 Firebase

您需要做的第一件事是转到Firebase 控制台并通过单击“+ 添加项目”按钮创建一个 Firebase 项目,如下所示:

Firebase 控制台

按照屏幕上的步骤完成项目创建。

在每个 Firebase 项目中,您可以创建不同的应用程序:适用于 Android、iOS、Web、Flutter 和 Unity。选择 Android 选项,如下所示:

Firebase 项目概述

然后按照下列步骤操作:

  1. 输入com.example.makeitso作为包名称,并可以选择输入昵称。对于此 Codelab,您不需要添加调试签名证书。
  2. 单击“下一步”注册您的应用并访问 Firebase 配置文件。
  3. 单击下载 google-services.json下载配置文件并将其保存在make-it-so-android/app目录中。
  4. 点击下一步。由于 Firebase SDK 已包含在示例项目的build.gradle文件中,因此单击Next跳至后续步骤
  5. 单击继续控制台以完成。

为了使Make it So应用程序正常工作,在跳转到代码之前,您需要在控制台中执行两件事:启用身份验证提供程序并创建 Firestore 数据库。首先,让我们启用身份​​验证,以便用户可以登录应用程序:

  1. “构建”菜单中,选择“身份验证” ,然后单击“开始”
  2. “登录方法”卡中,选择“电子邮件/密码” ,然后启用它。
  3. 接下来,单击添加新提供商并选择并启用Anonymous

接下来,设置 Firestore。您将使用 Firestore 存储登录用户的任务。每个用户都将在数据库集合中获得自己的文档

  1. “构建”菜单中,选择“Firestore” ,然后单击“创建数据库”
  2. 保持“在生产模式下启动”处于启用状态,然后单击“下一步”
  3. 出现提示时,选择 Cloud Firestore 数据的存储位置。开发生产应用程序时,您会希望该应用程序位于靠近大多数用户的区域,并且与其他 Firebase 服务(例如 Functions)相同。对于此 Codelab,您可以保留默认区域或选择离您最近的区域。
  4. 单击“启用”以配置您的 Firestore 数据库。

让我们花点时间为 Firestore 数据库构建强大的安全规则。打开 Firestore 仪表板并转到“规则”选项卡。然后更新安全规则,如下所示:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow create: if request.auth != null;
      allow read, update, delete: if request.auth != null && resource.data.userId == request.auth.uid;
    }
  }
}

这些规则基本上表明应用程序的任何登录用户都可以在任何集合中为自己创建文档。然后,一旦创建,只有创建该文档的用户才能查看、更新或删除该文档。

运行应用程序

现在您可以运行该应用程序了!在 Android Studio 中打开make-it-so-android/start文件夹并运行应用程序(可以使用 Android 模拟器或真实的 Android 设备来完成)。

3.Firebase身份验证

您要添加哪个功能?

Make It So示例应用程序的当前状态下,用户无需先登录即可开始使用该应用程序。它使用匿名身份验证来实现此目的。但是,匿名帐户不允许用户在其他设备上甚至在将来的会话中访问其数据。尽管匿名身份验证对于热引导很有用,但您应始终为用户提供转换为其他登录形式的选项。考虑到这一点,在此 Codelab 中,您将向Make It So应用添加电子邮件和密码身份验证。

是时候编码了!

用户通过输入电子邮件和密码创建帐户后,您需要向 Firebase 身份验证 API 请求电子邮件凭据,然后将新凭据链接到匿名帐户。在 Android Studio 中打开AccountServiceImpl.kt文件并更新linkAccount函数,使其如下所示:

模型/服务/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String) {
    val credential = EmailAuthProvider.getCredential(email, password)
    auth.currentUser!!.linkWithCredential(credential).await()
}

现在打开SignUpViewModel.kt并在onSignUpClick函数的launchCatching块内调用服务linkAccount函数:

屏幕/sign_up/SignUpViewModel.kt

launchCatching {
    accountService.linkAccount(email, password)
    openAndPopUp(SETTINGS_SCREEN, SIGN_UP_SCREEN)
}

首先,它尝试进行身份验证,如果调用成功,它将进入下一个屏幕( SettingsScreen )。当您在launchCatching块内执行这些调用时,如果第一行发生错误,异常将被捕获并处理,并且根本不会到达第二行。

再次打开SettingsScreen后,您需要确保“登录”“创建帐户”选项消失,因为现在用户已经通过身份验证。为此,我们让SettingsViewModel监听当前用户的状态(在AccountService.kt中可用),以检查该帐户是否是匿名的。为此,请更新SettingsViewModel.kt中的uiState ,如下所示:

屏幕/设置/SettingsViewModel.kt

val uiState = accountService.currentUser.map {
    SettingsUiState(it.isAnonymous)
}

您需要做的最后一件事是更新SettingsScreen.kt中的uiState以收集SettingsViewModel发出的状态:

屏幕/设置/SettingsScreen.kt

val uiState by viewModel.uiState.collectAsState(
    initial = SettingsUiState(false)
)

现在,每次用户更改时, SettingsScreen都会重新组合以根据用户的新身份验证状态显示选项。

测试时间到了!

运行Make it So并通过单击屏幕右上角的齿轮图标导航至设置。从那里,单击创建帐户选项:

让它如此设置屏幕Make it So 注册屏幕

输入有效的电子邮件和强密码来创建您的帐户。它应该可以工作,您应该被重定向到设置页面,您将在其中看到两个新选项:注销和删除您的帐户。您可以通过单击“用户”选项卡来检查在 Firebase 控制台的“身份验证”仪表板中创建的新帐户。

4.云Firestore

您要添加哪个功能?

对于 Cloud Firestore,您将向 Firestore 集合添加一个侦听器,该集合存储表示Make it So中显示的任务的文档。添加此侦听器后,您将收到对此集合所做的每个更新。

是时候编码了!

StorageServiceImpl.kt中的可用Flow更新为如下所示:

模型/服务/impl/StorageServiceImpl.kt

override val tasks: Flow<List<Task>>
    get() =
      auth.currentUser.flatMapLatest { user ->
        firestore.collection(TASK_COLLECTION).whereEqualTo(USER_ID_FIELD, user.id).dataObjects()
      }

此代码根据user.id将侦听器添加到任务集合中。每个任务都由名为tasks集合中的一个文档表示,并且每个任务都有一个名为userId的字段。请注意,如果currentUser的状态发生变化(例如通过注销),将发出新的Flow

现在您需要使TasksViewModel.kt中的Flow反映与服务中相同的流:

屏幕/任务/TasksViewModel.kt

val tasks = storageService.tasks

最后一件事是使TasksScreens.kt中代表 UI 的composable function了解此流程并将其收集为状态。每次状态发生变化时,可组合函数都会自动重组并向用户显示最新的状态。将其添加到TasksScreen composable function中:

屏幕/任务/TasksScreen.kt

val tasks = viewModel
    .tasks
    .collectAsStateWithLifecycle(emptyList())

一旦可组合函数可以访问这些状态,您就可以更新LazyColumn (这是用于在屏幕上显示列表的结构),如下所示:

屏幕/任务/TasksScreen.kt

LazyColumn {
    items(tasks.value, key = { it.id }) { taskItem ->
        TaskItem( [...] )
    }
}

测试时间到了!

为了测试它是否有效,请使用该应用程序添加一个新任务(通过单击屏幕右下角的添加按钮)。任务创建完成后,它应该会显示在 Firestore 控制台的 Firestore 集合中。如果您使用同一帐户在其他设备上登录Make it So ,您将能够编辑您的待办事项并观看它们在所有设备上实时更新。

5. 性能监控

您要添加哪个功能?

性能是需要注意的一个非常重要的事情,因为如果性能不好,用户很可能会放弃使用你的应用程序,并且他们需要花费太多时间来使用它来完成一个简单的任务。这就是为什么有时收集有关用户在应用程序中进行的特定旅程的一些指标很有用。为了帮助您实现这一点,Firebase 性能监控提供了自定义跟踪。按照后续步骤添加自定义跟踪并测量Make it So中不同代码段的性能。

是时候编码了!

如果打开Performance.kt文件,您将看到一个名为 Trace 的内联函数。此函数调用性能监控 API 创建自定义跟踪,并将跟踪名称作为参数传递。您看到的另一个参数是您希望监视的代码块。为每个跟踪收集的默认指标是完全运行所需的时间:

模型/服务/Performance.kt

inline fun <T> trace(name: String, block: Trace.() -> T): T = Trace.create(name).trace(block)

您可以选择您认为需要测量的代码库部分并向其中添加自定义跟踪。以下是向您之前在此 Codelab 中看到的linkAccount函数(在AccountServiceImpl.kt中)添加自定义跟踪的示例:

模型/服务/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String): Unit =
  trace(LINK_ACCOUNT_TRACE) {
      val credential = EmailAuthProvider.getCredential(email, password)
      auth.currentUser!!.linkWithCredential(credential).await()
  }

现在轮到你了!将一些自定义跟踪添加到Make it So应用程序,然后继续下一部分以测试它是否按预期工作。

测试时间到了!

添加完自定义迹线后,运行应用程序并确保多次使用您想要测量的功能。然后前往 Firebase 控制台并转到Performance 仪表板。在屏幕底部,您将找到三个选项卡:网络请求自定义跟踪屏幕渲染

转到“自定义跟踪”选项卡,检查您在代码库中添加的跟踪是否显示在那里,并且您可以看到执行这些代码片段通常需要多少时间。

6. 远程配置

您要添加哪个功能?

远程配置有多种用例,从远程更改应用程序的外观到为不同的用户群体配置不同的行为。在此 Codelab 中,您将使用远程配置创建一个功能切换,该功能将在Make it So应用上显示或隐藏新的编辑任务功能。

是时候编码了!

您需要做的第一件事是在 Firebase 控制台中创建配置。为此,您需要导航到远程配置仪表板并单击添加参数按钮。根据下图填写字段:

远程配置创建参数对话框

填写完所有字段后,您可以单击“保存”按钮,然后单击“发布” 。现在参数已创建并可用于您的代码库,您需要添加将获取新值到您的应用程序的代码。打开ConfigurationServiceImpl.kt文件并更新这两个函数的实现:

模型/服务/impl/ConfigurationServiceImpl.kt

override suspend fun fetchConfiguration(): Boolean {
  return remoteConfig.fetchAndActivate().await()
}

override val isShowTaskEditButtonConfig: Boolean
  get() = remoteConfig[SHOW_TASK_EDIT_BUTTON_KEY].asBoolean()

第一个函数从服务器获取值,并在应用程序启动后立即调用SplashViewModel.kt中的函数。这是确保从一开始就在所有屏幕中提供最新值的最佳方法。如果稍后当用户正在做某事时更改 UI 或应用程序的行为,这不是一个好的用户体验!

第二个函数返回为您刚刚在控制台中创建的参数发布的布尔值。您需要通过将以下内容添加到loadTaskOptions函数来在TasksViewModel.kt中检索此信息:

屏幕/任务/TasksViewModel.kt

fun loadTaskOptions() {
  val hasEditOption = configurationService.isShowTaskEditButtonConfig
  options.value = TaskActionOption.getOptions(hasEditOption)
}

您正在检索第一行的值,并使用它加载第二行任务项的菜单选项。如果值为false ,则意味着菜单将不包含编辑选项。现在您已经有了选项列表,您需要让 UI 正确显示它。当您使用 Jetpack Compose 构建应用程序时,您需要寻找声明TasksScreen UI 外观的可composable function 。因此,打开TasksScreen.kt文件并更新LazyColum以指向TasksViewModel.kt中可用的选项:

屏幕/任务/TasksScreen.kt

val options by viewModel.options

LazyColumn {
  items(tasks.value, key = { it.id }) { taskItem ->
    TaskItem(
      options = options,
      [...]
    )
  }
}

TaskItem是另一个composable function ,它声明单个任务的 UI 应该是什么样子。每个任务都有一个菜单,其中包含当用户单击其末尾的三点图标时显示的选项。

测试时间到了!

现在您可以运行该应用程序了!检查您使用 Firebase 控制台发布的值是否与应用的行为匹配:

  • 如果为false ,则单击三点图标时您应该只会看到两个选项;
  • 如果是true ,则单击三点图标时您应该会看到三个选项;

尝试在控制台中更改该值几次并重新启动应用程序。这就是使用远程配置在您的应用程序中启动新功能是多么容易!

7. 恭喜

恭喜,您已成功使用 Firebase 和 Jetpack Compose 构建了 Android 应用!

您将 Firebase 身份验证、性能监控、远程配置和 Cloud Firestore 添加到完全使用 Jetpack Compose 构建 UI 的 Android 应用程序中,并使其适合推荐的 MVVM 架构!

进一步阅读

参考文档