使用 Firebase Data Connect(Android)构建应用

1. 概览

ddc52cd46f923cf1.png

在此 Codelab 中,您将将 Firebase Data Connect 与 Cloud SQL 数据库集成,以构建电影评价 Android 应用。您将学习如何:

  • 为 Firebase Data Connect 编写 GraphQL 架构
  • 写入查询和更改
  • 实现用户身份验证以保护您的数据

前提条件

  • 最新版本的 Android Studio
  • 搭载 API 级别 23 或更高级别的 Android 模拟器

学习内容

  • 如何使用本地模拟器设置 Firebase Data Connect。
  • 如何使用 Data Connect 和 GraphQL 设计数据架构。
  • 如何为影评应用编写查询和更改。
  • 如何生成 Kotlin SDK 并在 Android 应用中使用它。
  • (可选)如何将 Data Connect 服务部署到生产环境。

2. 设置示例项目

创建 Firebase 项目

  1. 使用您的 Google 账号登录 Firebase 控制台
  2. Firebase 控制台中,点击“添加项目”。
  3. 输入 Firebase 项目的名称(例如“电影评价”),然后点击“继续”。
  4. 系统可能会要求您启用 Google Analytics,但对于本 Codelab 而言,您的选择无关紧要。
  5. 大约一分钟后,您的 Firebase 项目就准备就绪了。点击“继续”。

下载代码

运行以下命令以克隆此 Codelab 的示例代码。这将在您的机器上创建一个名为 codelab-dataconnect-android 的目录:

git clone https://github.com/firebaseextended/codelab-dataconnect-android.git

如果您的机器上没有 git,您也可以直接从 GitHub 下载代码

添加 Firebase 配置

  1. Firebase 控制台中,选择左侧导航栏中的“Project Overview”(项目概览)。点击“Android”按钮以选择平台。当系统提示输入软件包名称时,请使用 com.google.firebase.example.dataconnect
  2. 点击“注册应用”,然后按照说明下载 google-services.json 文件,并将其移至您刚刚下载的代码的 app/ 目录中。然后点击“下一步”。

3. 设置 Data Connect

安装

自动安装

codelab-dataconnect-android 目录中运行以下命令:

curl -sL https://firebase.tools/dataconnect | bash

此脚本会尝试为您设置开发环境并启动基于浏览器的 IDE。此 IDE 提供了一些工具(包括预捆绑的 VS Code 扩展程序),可帮助您管理架构,定义要在应用中使用的查询和更改,以及生成强类型 SDK。

运行脚本后,VS Code 应会自动打开。

注意:如果您已安装桌面版 VS Code,该脚本应会自动打开它。如果脚本失败,请使用以下手动安装步骤。

手动安装

  1. 安装 Visual Studio Code
  2. 安装 Node.js
  3. 在 VS Code 中,打开 codelab-dataconnect-android 目录。
  4. Visual Studio Code Marketplace 安装 Firebase Data Connect 扩展程序。

在项目中初始化 Data Connect

在左侧面板中,点击 Firebase 图标以打开 Data Connect VS Code 扩展程序界面:

  1. 点击使用 Google 账号登录按钮。系统随即会打开一个浏览器窗口;请按照说明使用您的 Google 账号登录该扩展程序。ef59f25a9e9cbfff.png
  2. 点击关联 Firebase 项目按钮,然后在控制台中选择您之前创建的项目。951a836ba0682494.png

点击 Run firebase init 按钮,然后按照集成终端中的步骤操作。

配置 SDK 生成

点击“Run firebase init”按钮后,Firebase Data Connect 扩展程序应会为您初始化 dataconnect/ 目录。

在 VS Code 中,打开 dataconnect/connector/connector.yaml 文件,您会看到默认配置。为了更轻松地直观呈现此 Codelab 中的代码生成过程,请将 connectorId 更改为 movies,并将 package 更改为 com.google.firebase.example.dataconnect.generated

connectorId: movies
generate:
  kotlinSdk:
    outputDir: ../../app/src/main/java
    package: com.google.firebase.example.dataconnect.generated

如需了解每种状态的含义,请参阅下文:

  • connectorId - 此连接器的唯一名称。
  • outputDir - 将存储生成的 Data Connect SDK 的路径。此路径相对于包含 connector.yaml 文件的目录。
  • package - 要用于生成的 SDK 中的软件包名称。

启动 Firebase 模拟器

在 VS Code 中,点击启动模拟器按钮。

93fb67962e96a7cb.png

您应该会看到模拟器在集成终端中启动。如果它正确启动,您应该会看到如下所示的输出:

8504ae0080923823.png

将 Android 应用配置为使用本地模拟器

  1. 打开 Android Studio。
  2. 在 Android Studio 的欢迎界面中,点击“Open”按钮,然后选择 codelab-dataconnect-android 目录。等待 Gradle 同步。
  3. Gradle 同步完成后,打开 app/src/main/java/com/google/firebase/example/dataconnect/MainActivity.kt 文件并调用 useEmulator()
import com.google.firebase.example.dataconnect.generated.MoviesConnector
import com.google.firebase.example.dataconnect.generated.instance

class MainActivity : ComponentActivity() {
  ...

  // Initialize Firebase Data Connect
  MoviesConnector.instance.dataConnect.useEmulator("10.0.2.2", 9399)

  ...
}

4. 定义架构并预先填充数据库

在本部分中,您将在架构中定义电影应用中关键实体的结构和这些实体之间的关系。MovieUserReview 等实体会映射到数据库表,并使用 Firebase Data Connect 和 GraphQL 架构指令建立关系。

核心实体和关系

Movie 类型用于存储标题、类型和标签等关键详细信息,这些信息会被应用用于搜索和电影个人资料。User 类型用于跟踪用户互动,例如评价和收藏。Review 可将用户与电影相关联,让应用显示用户生成的评分和反馈。

“用户”表

“用户”类型用于定义通过发表影评或将电影列为收藏来与电影互动的用户实体。

在 VS Code 中,打开 dataconnect/schema/schema.gql 文件,然后取消备注(或添加)User 表定义:

# Users
# Suppose a user can leave reviews for movies
# user  -> reviews is a one to many relationship,
# movie -> reviews is a one to many relationship
# movie <-> user is a many to many relationship
type User @table {
  id: String! @col(name: "user_auth")
  username: String! @col(name: "username", dataType: "varchar(50)")
  # The following are generated by the user: User! field in the Review table
  # reviews_on_user 
  # movies_via_Review
}

电影表

Movie 类型定义了电影实体的主要结构,包括 title、genre、releaseYear 和 rating 等字段。

在 VS Code 中,打开 dataconnect/schema/schema.gql 文件,然后取消备注(或添加)Movie 表定义:

# Movies
type Movie @table {
  # The below parameter values are generated by default with @table, and can be edited manually.
  # implies directive `@col(name: "movie_id")`, generating a column name
  id: UUID! @default(expr: "uuidV4()")
  title: String!
  imageUrl: String!
  genre: String
}

MovieMetadata 表

MovieMetadata 类型与 Movie 类型建立一对一关系。其中包含电影导演等额外数据。

在 VS Code 中,打开 dataconnect/schema/schema.gql 文件,然后取消备注(或添加)MovieMetadata 表定义:

# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata @table {
  # @unique indicates a 1-1 relationship
  movie: Movie! @unique 
  # movieId: UUID <- this is created by the above reference
  rating: Float
  releaseYear: Int
  description: String
}

评价表

“评价”类型代表评价实体,并将“用户”和“电影”类型以多对多关系关联起来(一位用户可以留下许多评价,每部电影也可以有许多评价)。

在 VS Code 中,打开 dataconnect/schema/schema.gql 文件,然后取消备注(或添加)Review 表定义:

# Reviews
type Review @table(name: "Reviews", key: ["movie", "user"]) {
  id: UUID! @default(expr: "uuidV4()")
  user: User!
  movie: Movie!
  rating: Int
  reviewText: String
  reviewDate: Date! @default(expr: "request.time")
}

自动生成的字段和默认值

该架构使用 @default(expr: "uuidV4()") 等表达式自动生成唯一 ID 和时间戳。例如,在创建新记录时,Movie 和 Review 类型的 id 字段会自动填充 UUID。

插入模拟数据

架构定义完毕后,您现在可以使用模拟数据预先填充数据库以进行测试。

  1. 在 VS Code 中,打开 dataconnect/moviedata_insert.gql。确保 Firebase Data Connect 扩展程序中的模拟器正在运行。
  2. 您应该会在文件顶部看到“Run (local)”(运行 [本地])按钮。点击此按钮可将模拟电影数据插入数据库。

b070f025e573ab9b.png

  1. 检查 Data Connect 执行终端,确认数据已成功添加。

e2058cb4db857058.png

数据准备就绪后,请继续执行下一步,了解如何在 Data Connect 中创建查询。

5. 创建查询以列出电影

首先,创建一个用于列出电影的查询。您将为每部电影提取 id、title、imageUrl 和 genre。

定义查询

在 VS Code 中,打开 dataconnect/connector/queries.gql 文件,然后取消注释(或添加)ListMovies 查询:

query ListMovies @auth(level: PUBLIC) {
  movies {
    id
    title
    imageUrl
    genre
  }
}

如需测试新查询,请点击“Run (local)”(运行 [本地])按钮,以便对本地数据库执行查询。数据库中的电影列表应显示在 Data Connect 执行终端的“结果”部分下。

822bf32321df4716.png

从 Android 应用调用它

现在,您已在 Data Connect 模拟器中测试了查询,接下来可以将其添加到应用中了。

在 Android Studio 中,打开 app/src/main/java/com/google/firebase/example/dataconnect/MoviesScreen.kt 文件,然后添加以下代码以以网格格式显示电影列表:

import com.google.firebase.example.dataconnect.generated.ListMoviesQuery
import com.google.firebase.example.dataconnect.generated.MoviesConnector
import com.google.firebase.example.dataconnect.generated.execute
import com.google.firebase.example.dataconnect.generated.instance

@Composable
fun MoviesScreen(
    onMovieClicked: (id: String) -> Unit
) {
    var movies by remember { mutableStateOf(emptyList<ListMoviesQuery.Data.MoviesItem>()) }
    LaunchedEffect(Unit) {
        // Queries need to be executed in a coroutine context
        try {
          movies = MoviesConnector.instance.listMovies.execute().data.movies
        } catch (e: Exception) {
          // Will be done at a later step
        }
    }
    LazyVerticalGrid(GridCells.Adaptive(150.dp)) {
        items(movies) { movie ->
            MovieCard(
                movieId = movie.id.toString(),
                movieTitle = movie.title,
                movieImageUrl = movie.imageUrl,
                movieGenre = movie.genre,
                onMovieClicked = {
                    onMovieClicked(movie.id.toString())
                }
            )
        }
    }
}

运行应用

在 Android Studio 中,点击“Run”按钮以在 Android 模拟器中启动应用。

应用启动后,您应该会看到如下所示的屏幕:

ddc52cd46f923cf1.png

6. 创建电影详情查询

现在,应用可以列出电影了,接下来我们来创建一个查询,以显示每部电影的详细信息。

定义查询

在 VS Code 中,打开 dataconnect/connector/queries.gql 文件,然后取消注释(或添加)GetMovieById 查询:

# Get movie by id
query GetMovieById($id: UUID!) @auth(level: PUBLIC) {
  movie(id: $id) {
    id
    title
    imageUrl
    genre
    metadata: movieMetadata_on_movie {
      rating
      releaseYear
      description
    }
    reviews: reviews_on_movie {
      id
      reviewText
      reviewDate
      rating
      user {
        id
        username
      }
    }
  }
}

从 Android 应用调用它

在 Android Studio 中,打开 app/src/main/java/com/google/firebase/example/dataconnect/MovieDetailScreen.kt 文件并添加以下代码:

importcom.google.firebase.example.dataconnect.generated.GetMovieByIdQuery
importcom.google.firebase.example.dataconnect.generated.MoviesConnector
importcom.google.firebase.example.dataconnect.generated.execute
importcom.google.firebase.example.dataconnect.generated.instance

@Composable
fun MovieDetailScreen(
    movieId: String
) {
    var movie by remember { mutableStateOf<GetMovieByIdQuery.Data.Movie?>(null) }
    LaunchedEffect(Unit) {
        movie = MoviesConnector.instance.getMovieById.execute(
            UUID.fromString(movieId)
        ).data.movie
    }
    if (movie == null) {
        LoadingScreen()
    } else {
        MovieDetails(
            movieTitle = movie!!.title,
            movieImageUrl = movie!!.imageUrl,
            movieGenre = movie!!.genre,
            movieRating = movie!!.metadata?.rating,
            movieReleaseYear = movie!!.metadata?.releaseYear,
            movieDescription = movie!!.metadata?.description,
        )
    }
}

运行应用

在 Android Studio 中,点击“Run”按钮以在 Android 模拟器中启动应用。

7. 创建用于插入用户的更改

现在,应用已经能够显示数据,接下来就可以从应用中添加新数据了。为了安全地执行此操作,您应使用 Firebase Authentication。

在此 Codelab 中,应用使用匿名身份验证来让用户登录,但为了让应用更安全,不妨考虑使用其他身份验证方法,例如电子邮件/密码身份验证或联合身份提供方。

定义更改

在 VS Code 中,打开 dataconnect/connector/mutations.gql 文件,然后取消注释(或添加)UpsertUser 查询:

# Upsert (update or insert) a user's username based on their auth.uid
mutation UpsertUser($username: String!) @auth(level: USER) {
  user_upsert(
    data: {
      id_expr: "auth.uid"
      username: $username
    }
  )
}

从 Android 应用调用它

在 Android Studio 中,打开 app/src/main/java/com/google/firebase/example/dataconnect/MainActivity.kt 文件并调用该更改:

import com.google.firebase.example.dataconnect.generated.execute

LaunchedEffect(Unit) {
  // If there's no user signed in, sign in an anonymous user
  if (firebaseAuth.currentUser == null) {
    firebaseAuth.signInAnonymously().await()
    val newUsername = getRandomUsername()
    MoviesConnector.instance.upsertUser.execute(newUsername)
  }
}

运行应用

在 Android Studio 中,点击“Run”按钮以在 Android 模拟器中启动应用。

8. 恭喜

恭喜!您已成功将 Firebase Data Connect 添加到 Android 应用!

现在,您已了解设置 Data Connect、创建查询和更改以及处理用户身份验证所需的关键步骤。

后续步骤

可选:部署到生产环境

到目前为止,此应用仅使用了 Firebase 模拟器。如果您想了解如何将此应用部署到真实的 Firebase 项目,请继续执行下一步。

9. (可选)部署应用

到目前为止,此应用完全在本地运行,所有数据都包含在 Firebase Emulator Suite 中。在本部分中,您将了解如何配置 Firebase 项目,以便此应用在生产环境中正常运行。

启用 Firebase Authentication

在 Firebase 控制台中,前往“Authentication”部分,然后点击“Get started”(开始)。前往“登录方法”标签页,然后从提供方中选择“匿名登录”选项。

启用“匿名登录”方法,然后点击“保存”。

部署 Firebase Data Connect 架构

重要提示:如果这是您首次在项目中部署架构,此过程将创建一个 Cloud SQL PostgreSQL 实例,可能需要大约 15 分钟。只有在 Cloud SQL 实例准备就绪并与 Firebase Data Connect 集成后,您才能进行部署。

  1. 在 Firebase Data Connect VS Code 扩展程序界面中,点击部署到生产环境
  2. 您可能需要审核架构更改并批准可能破坏性修改。系统会提示您执行以下操作:
    • 使用 firebase dataconnect:sql:diff 查看架构更改
    • 对更改感到满意后,使用 firebase dataconnect:sql:migrate 启动的流程应用更改

您的 Cloud SQL for PostgreSQL 实例将更新为包含最终部署的架构和数据。您可以在 Firebase 控制台中监控状态。

现在,您可以点击 Firebase Data Connect 面板中的“Run(Production)”(运行 [生产]),就像在本地模拟器中一样,将数据添加到生产环境。