1. 准备工作
在此 Codelab 中,您将学习如何在本地开发过程中将 Firebase Emulator Suite 与 Flutter 搭配使用。您将学习如何通过 Emulator Suite 使用电子邮件地址/密码身份验证,以及如何在 Firestore 模拟器中读取和写入数据。最后,您将从模拟器中导入和导出数据,以便在每次返回开发时处理相同的虚构数据。
前提条件
此 Codelab 假定您具有一些 Flutter 经验。如果没有,您可能需要先了解基础知识。以下链接非常有用:
您还应具备一定程度的 Firebase 经验,但如果您从未将 Firebase 添加到 Flutter 项目,也没有关系。如果您不熟悉 Firebase 控制台,或者第一次使用 Firebase,请先查看以下链接:
您将创建的内容
此 Codelab 将指导您构建一个简单的日记应用。该应用将具有一个登录屏幕,以及一个可让您阅读过去的日记条目和创建新条目的屏幕。
学习内容
您将学习如何开始使用 Firebase,以及如何将 Firebase Emulator Suite 集成到和使用 Flutter 开发工作流中。我们将介绍以下 Firebase 主题:
请注意,仅涵盖介绍 Firebase Emulator Suite 所必需的主题。此 Codelab 将重点介绍如何将 Firebase 项目添加到您的 Flutter 应用,以及使用 Firebase Emulator Suite 进行开发。我们不会深入讨论 Firebase Authentication 或 Firestore。如果您不熟悉这些主题,建议您从“了解适用于 Flutter 的 Firebase”Codelab 开始学习。
所需条件
- 具备 Flutter 的实际运用知识,并且已安装 SDK
- Intellij JetBrains 或 VS Code 文本编辑器
- Google Chrome 浏览器(或您的其他首选 Flutter 开发目标。此 Codelab 中的一些终端命令将假定您在 Chrome 上运行应用)
2. 创建和设置 Firebase 项目
您需要完成的第一项任务是在 Firebase 的 Web 控制台中创建一个 Firebase 项目。此 Codelab 的大部分内容都将重点介绍 Emulator Suite,该套件使用本地运行的界面,但您必须先设置完整的 Firebase 项目。
创建 Firebase 项目
- 登录 Firebase 控制台。
- 在 Firebase 控制台中,点击添加项目(或创建项目),然后为您的 Firebase 项目输入一个名称(例如“Firebase-Flutter-Codelab”)。
- 点击各个项目创建选项。如果系统提示,请接受 Firebase 条款。跳过设置 Google Analytics(分析)的步骤,因为您不会为此应用使用 Google Analytics(分析)。
如需详细了解 Firebase 项目,请参阅了解 Firebase 项目。
您正在构建的应用使用了两个适用于 Flutter 应用的 Firebase 产品:
- Firebase Authentication:允许用户登录您的应用。
- Cloud Firestore:用于将结构化数据保存在云端,并在数据发生变化时收到即时通知。
这两个产品需要特殊配置或者需要使用 Firebase 控制台启用。
启用 Cloud Firestore
Flutter 应用使用 Cloud Firestore 保存日记条目。
启用 Cloud Firestore:
- 在 Firebase 控制台的 Build 部分中,点击 Cloud Firestore。
- 点击创建数据库。
- 选择以测试模式开始选项。阅读有关安全规则的免责声明。测试模式可确保您在开发过程中可以随意向数据库写入数据。点击 Next。
- 选择数据库的位置(只需使用默认位置即可)。请注意,此位置以后无法更改。
- 点击启用。
3. 设置 Flutter 应用
在我们开始之前,您需要下载起始代码并安装 Firebase CLI。
获取起始代码
从命令行克隆 GitHub 代码库:
git clone https://github.com/flutter/codelabs.git flutter-codelabs
或者,如果您已安装 GitHub 的 cli 工具,请运行以下命令:
gh repo clone flutter/codelabs flutter-codelabs
您应将示例代码克隆到 flutter-codelabs
目录中,该目录包含一系列 Codelab 的代码。此 Codelab 的代码位于 flutter-codelabs/firebase-emulator-suite
中。
flutter-codelabs/firebase-emulator-suite
下的目录结构由两个 Flutter 项目组成。一个名为 complete
,如果您想跳过,或者交叉引用您自己的代码,可以引用它。另一个项目名为 start
。
您希望起始代码位于 flutter-codelabs/firebase-emulator-suite/start
目录中。打开该目录,或将该目录导入您的首选 IDE。
cd flutter-codelabs/firebase-emulator-suite/start
安装 Firebase CLI
Firebase CLI 提供了用于管理 Firebase 项目的工具。如需使用 Emulator Suite,需要安装 CLI,因此您需要安装。
您可以通过多种方式安装 CLI。如果您使用的是 MacOS 或 Linux,最简单的方法是从终端运行此命令:
curl -sL https://firebase.tools | bash
安装 CLI 后,您必须进行 Firebase 身份验证。
- 运行以下命令,使用您的 Google 账号登录 Firebase:
firebase login
- 此命令会将您的本地机器与 Firebase 关联,并授予您对 Firebase 项目的访问权限。
- 列出您的 Firebase 项目,测试 CLI 是否已正确安装以及是否可以访问您的帐号。运行以下命令:
firebase projects:list
- 显示的列表应与 Firebase 控制台中列出的 Firebase 项目相同。您应该至少看到 firebase-flutter-codelab。
安装 FlutterFire CLI
FlutterFire CLI 基于 Firebase CLI 构建,可让您更轻松地将 Firebase 项目与 Flutter 应用集成。
首先,安装 CLI:
dart pub global activate flutterfire_cli
确保已安装 CLI。在 Flutter 项目目录中运行以下命令,并确保 CLI 会输出帮助菜单。
flutterfire --help
使用 Firebase CLI 和 FlutterFire CLI 将 Firebase 项目添加到您的 Flutter 应用
安装这两个 CLI 后,您只需使用几个终端命令,即可设置各个 Firebase 产品(如 Firestore)、下载模拟器,以及将 Firebase 添加到您的 Flutter 应用。
首先,运行以下命令完成 Firebase 设置:
firebase init
此命令将引导您回答设置项目所需的一系列问题。以下屏幕截图展示了该流程:
- 当系统提示您选择功能时,请选择“Firestore”和“模拟器”。(没有 Authentication 选项,因为它不使用可从 Flutter 项目文件修改的配置。)
- 接下来,在出现提示时选择“使用现有项目”。
- 现在,选择您在上一步中创建的项目:flutter-firebase-codelab。
- 接下来,系统会询问您一系列关于为将生成的文件命名的问题。建议您为每个问题按下“Enter”键以选择默认题目。
- 最后,您需要配置模拟器。从列表中选择“Firestore 和 Authentication”,然后按“Enter”键,回答与要用于每个模拟器的特定端口有关的每个问题。当系统询问您是否要使用模拟器界面时,您应选择默认值,即“是”。
在完成此过程后,您应该会看到类似于以下屏幕截图的输出。
重要提示:您的输出可能与我的输出略有不同,如以下屏幕截图所示,因为如果您已下载模拟器,最后一个问题将默认为“No”。
配置 FlutterFire
接下来,您可以使用 FlutterFire 生成所需的 Dart 代码,以便在您的 Flutter 应用中使用 Firebase。
flutterfire configure
运行此命令时,系统会提示您选择要使用的 Firebase 项目以及要设置的平台。在此 Codelab 中,示例使用的是 Flutter Web,但您可以将 Firebase 项目设置为使用所有选项。
以下屏幕截图显示了您需要回答的提示。
此屏幕截图显示了此过程结束时的输出。如果您熟悉 Firebase,就会发现不必在控制台中创建应用,FlutterFire CLI 会为您代劳。
将 Firebase 软件包添加到 Flutter 应用
最后一步是将相关的 Firebase 软件包添加到您的 Flutter 项目。在终端中,确保您位于 Flutter 项目的根目录 flutter-codelabs/firebase-emulator-suite/start
。然后,运行以下三个命令:
flutter pub add firebase_core
flutter pub add firebase_auth
flutter pub add cloud_firestore
这些是您将在此应用中使用的唯一软件包。
4.启用 Firebase 模拟器
到目前为止,Flutter 应用和您的 Firebase 项目已设置为能够使用模拟器,但您仍然需要告知 Flutter 代码将传出的 Firebase 请求重新路由到本地端口。
首先,将 Firebase 初始化代码和模拟器设置代码添加到 main.dart.
中的 main
函数
main.dart
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'app_state.dart'; import 'firebase_options.dart'; import 'logged_in_view.dart'; import 'logged_out_view.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); if (kDebugMode) { try { FirebaseFirestore.instance.useFirestoreEmulator('localhost', 8080); await FirebaseAuth.instance.useAuthEmulator('localhost', 9099); } catch (e) { // ignore: avoid_print print(e); } } runApp(MyApp()); }
前几行代码用于初始化 Firebase。几乎普遍的做法是,如果您在 Flutter 应用中使用 Firebase,需要先调用 WidgetsFlutterBinding.ensureInitialized
和 Firebase.initializeApp
。
之后,以 if (kDebugMode)
行开头的代码会指示您的应用以模拟器为目标,而不是正式版 Firebase 项目。kDebugMode
可确保仅在您处于开发环境时才会定位到模拟器。由于 kDebugMode
是一个常量值,因此 Dart 编译器知道在发布模式下完全移除该代码块。
启动模拟器
您应先启动模拟器,然后再启动 Flutter 应用。首先,在终端中运行以下命令来启动模拟器:
firebase emulators:start
此命令会启动模拟器,并显示 localhost 端口,以便我们与其进行交互。运行该命令时,您应该会看到类似如下所示的输出:
此输出信息可告诉您哪些模拟器正在运行,以及您可以在哪里查看模拟器。首先,查看位于 localhost:4000
的模拟器界面。
这是本地模拟器界面的首页。它会列出所有可用的模拟器,每个模拟器都带有开启或关闭状态标签。
5. Firebase Auth 模拟器
您将使用的第一个模拟器是 Authentication 模拟器。点击界面中“Authentication”卡片上的“Go to emulator”以开始使用 Auth 模拟器,您将看到如下所示的页面:
此页面与 Auth 网页版控制台页面具有一些相似之处。它有一个表格,和在线控制台一样列出用户,并且允许您手动添加用户。这里的一个很大区别是,模拟器上可用的唯一身份验证方法选项是电子邮件地址和密码。这足以进行本地开发。
接下来,您将完成向 Firebase Auth 模拟器添加用户的过程,然后通过 Flutter 界面使该用户登录。
添加用户
点击“添加用户”按钮,然后在表单中填写以下信息:
- 显示名称:Dash
- 电子邮件地址: dash@email.com
- 密码:短划线
提交表单,您会看到表中现在包含一个用户。现在,您可以更新代码以使用该用户身份登录。
logged_out_view.dart
LoggedOutView
widget 中唯一需要更新的代码位于用户按登录按钮时触发的回调中。将代码更新为如下所示:
class LoggedOutView extends StatelessWidget { final AppState state; const LoggedOutView({super.key, required this.state}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Firebase Emulator Suite Codelab'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'Please log in', style: Theme.of(context).textTheme.displaySmall, ), Padding( padding: const EdgeInsets.all(8.0), child: ElevatedButton( onPressed: () async { await state.logIn('dash@email.com', 'dashword').then((_) { if (state.user != null) { context.go('/'); } }); }, child: const Text('Log In'), ), ), ], ), ), ); } }
更新后的代码会将 TODO
字符串替换为您在身份验证模拟器中创建的电子邮件地址和密码。在下一行代码中,if(true)
行已被替换为用于检查 state.user
是否为 null 的代码。AppClass
中的代码进一步说明了这一问题。
app_state.dart
AppState
中代码的两部分需要更新。首先,为类成员 AppState.user 提供 firebase_auth
软件包中的类型 User
,而不是 Object
类型。
然后,填写 AppState.login
方法,如下所示:
import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'entry.dart'; class AppState { AppState() { _entriesStreamController = StreamController.broadcast(onListen: () { _entriesStreamController.add([ Entry( date: '10/09/2022', text: lorem, title: '[Example] My Journal Entry', ) ]); }); } User? user; // <-- changed variable type Stream<List<Entry>> get entries => _entriesStreamController.stream; late final StreamController<List<Entry>> _entriesStreamController; Future<void> logIn(String email, String password) async { final credential = await FirebaseAuth.instance .signInWithEmailAndPassword(email: email, password: password); if (credential.user != null) { user = credential.user!; _listenForEntries(); } else { print('no user!'); } } // ... }
用户的类型定义现在为 User?
。该 User
类来自 Firebase Authentication,并提供 User.displayName
等所需信息,我们将对此进行详细介绍。
这是在 Firebase Auth 中使用电子邮件地址和密码登录用户所需的基本代码。它会调用 FirebaseAuth 进行登录,这会返回一个 Future<UserCredential>
对象。当 Future 变成已完成状态时,此代码会检查 UserCredential
上是否附加了 User
。如果凭据对象上有用户,则表示用户已成功登录,您可以设置 AppState.user
属性。如果没有,则表示出现错误,并且输出结果。
请注意,此方法中唯一专用于此应用的代码行(而不是常规 FirebaseAuth 代码)是对 _listenForEntries
方法的调用,将在下一步中介绍。
待办事项:操作图标 - 重新加载您的应用,然后在呈现时按“登录”按钮。这会导致应用转到顶部显示“Welcome Back, Person!”的页面。身份验证必须正常运行,因为您可以使用它导航到此页面,但需要对 logged_in_view.dart
进行细微更新,以显示用户的真实姓名。
logged_in_view.dart
更改 LoggedInView.build
方法中的第一行:
class LoggedInView extends StatelessWidget { final AppState state; LoggedInView({super.key, required this.state}); final PageController _controller = PageController(initialPage: 1); @override Widget build(BuildContext context) { final name = state.user!.displayName ?? 'No Name'; return Scaffold( // ...
现在,下面这行代码会从 AppState
对象的 User
属性中获取 displayName
。此 displayName
是在定义第一位用户时在模拟器中设置的。现在,当您登录时,您的应用应显示“Welcome back, Dash!”,而不是 TODO
。
6. 对 Firestore 模拟器执行数据读写操作
首先,查看 Firestore 模拟器。在模拟器界面首页 (localhost:4000
),点击 Firestore 卡片上的“转到模拟器”。它应如下所示:
模拟器:
Firebase 控制台:
如果您有任何使用 Firestore 的经验,就会发现此页面与 Firebase 控制台的 Firestore 页面类似。不过,这两者之间有一些显著的差异。
- 只需点按一下按钮,即可清除所有数据。这对于生产数据来说很危险,但有助于快速迭代!如果您正在处理新项目,并且数据模型发生了变化,则很容易清除。
- 有一个“请求”标签页。通过此标签页,您可以监视向此模拟器发出的传入请求。稍后,我将更详细地讨论此标签。
- 没有针对“规则”、“索引”或“使用情况”的标签页。有一种工具(在下一部分会对此进行讨论)可帮助编写安全规则,但您无法为本地模拟器设置安全规则。
总而言之,此版本的 Firestore 提供了更多在开发过程中实用的工具,并移除了生产环境中所需的工具。
写入 Firestore
在讨论模拟器中的“Requests”标签页之前,请先发出请求。这需要更新代码。首先在应用中连接表单,将新日志 Entry
写入 Firestore。
提交 Entry
的大致流程如下:
- 用户填写表单并按了“
Submit
”按钮 - 界面调用
AppState.writeEntryToFirebase
AppState.writeEntryToFirebase
向 Firebase 添加一个条目
第 1 步或第 2 步所涉及的代码均无需更改。需要为第 3 步添加的唯一代码将添加到 AppState
类中。对 AppState.writeEntryToFirebase
进行以下更改。
app_state.dart
import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'entry.dart'; class AppState { AppState() { _entriesStreamController = StreamController.broadcast(onListen: () { _entriesStreamController.add([ Entry( date: '10/09/2022', text: lorem, title: '[Example] My Journal Entry', ) ]); }); } User? user; Stream<List<Entry>> get entries => _entriesStreamController.stream; late final StreamController<List<Entry>> _entriesStreamController; Future<void> logIn(String email, String password) async { final credential = await FirebaseAuth.instance .signInWithEmailAndPassword(email: email, password: password); if (credential.user != null) { user = credential.user!; _listenForEntries(); } else { print('no user!'); } } void writeEntryToFirebase(Entry entry) { FirebaseFirestore.instance.collection('Entries').add(<String, String>{ 'title': entry.title, 'date': entry.date.toString(), 'text': entry.text, }); } // ... }
writeEntryToFirebase 方法中的代码会获取对 Firestore 中名为“Entries”(条目)的集合的引用。然后,它会添加一个新条目,该条目必须为 Map<String, String>
类型。
在这种情况下,Firestore 中不存在“Entries”集合,因此 Firestore 创建了一个集合。
添加该代码后,执行热重载或重启应用,登录并转到 EntryForm
视图。您可以在表单中填写自己喜欢的任何 Strings
。(“Date”字段可接受任何字符串,因为在此 Codelab 中已简化。它没有进行强有力的验证,也未以任何方式关注 DateTime
对象。)
在表单上按“提交”。应用不会执行任何操作,但您可以在模拟器界面中查看新条目。
Firestore 模拟器中的“请求”标签页
在界面中,转到 Firestore 模拟器并查看“Data”标签页。您应该会看到,数据库的根目录下现在有一个名为“Entries”(条目)的集合。其中应该有一份文档,其中包含您在表单中输入的信息。
这确认了 AppState.writeEntryToFirestore
有效,现在,您可以在“Requests”标签页中进一步浏览该请求。现在点击该标签页。
Firestore 模拟器请求
在这里,您应该会看到类似于以下内容的列表:
您可以点击进入其中任一列表项,查看很多有用的信息。点击与创建新日记条目的请求对应的 CREATE
列表项。您将看到一个如下所示的新表格:
如上所述,Firestore 模拟器提供了用于开发应用安全规则的工具。此视图准确显示了该请求通过(或失败,如果是这种情况)的安全规则中的哪一行。在更强大的应用中,安全规则可能会扩展且会进行多次授权检查。此视图用于帮助编写和调试这些授权规则。
它还提供了一种简单的方法来检查此请求的每一部分,包括元数据和身份验证数据。此数据用于编写复杂的授权规则。
从 Firestore 读取数据
Firestore 使用数据同步功能将更新后的数据推送到已连接的设备。在 Flutter 代码中,您可以监听(或订阅)Firestore 集合和文档,每当数据发生更改时,您的代码都会收到通知。在此应用中,在名为 AppState._listenForEntries
的方法中监听 Firestore 更新。
此代码分别与名为 AppState._entriesStreamController
和 AppState.entries
的 StreamController
和 Stream
结合使用。该代码已经编写好,界面中显示 Firestore 数据所需的所有代码也是如此。
更新 _listenForEntries
方法以匹配以下代码:
app_state.dart
import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'entry.dart'; class AppState { AppState() { _entriesStreamController = StreamController.broadcast(onListen: () { _entriesStreamController.add([ Entry( date: '10/09/2022', text: lorem, title: '[Example] My Journal Entry', ) ]); }); } User? user; Stream<List<Entry>> get entries => _entriesStreamController.stream; late final StreamController<List<Entry>> _entriesStreamController; Future<void> logIn(String email, String password) async { final credential = await FirebaseAuth.instance .signInWithEmailAndPassword(email: email, password: password); if (credential.user != null) { user = credential.user!; _listenForEntries(); } else { print('no user!'); } } void writeEntryToFirebase(Entry entry) { FirebaseFirestore.instance.collection('Entries').add(<String, String>{ 'title': entry.title, 'date': entry.date.toString(), 'text': entry.text, }); } void _listenForEntries() { FirebaseFirestore.instance .collection('Entries') .snapshots() .listen((event) { final entries = event.docs.map((doc) { final data = doc.data(); return Entry( date: data['date'] as String, text: data['text'] as String, title: data['title'] as String, ); }).toList(); _entriesStreamController.add(entries); }); } // ... }
此代码会监听 Firestore 中的“Entries”集合。当 Firestore 通知此客户端有新数据时,它会传递该数据,并且 _listenForEntries
中的代码会将其所有子文档更改为可供应用使用的对象 (Entry
)。然后,它会将这些条目添加到名为 _entriesStreamController
的 StreamController
(界面正在监听)中。此代码是唯一需要的更新。
最后,回想一下 AppState.logIn
方法会调用 _listenForEntries
,这会在用户登录后开始监听过程。
// ... Future<void> logIn(String email, String password) async { final credential = await FirebaseAuth.instance .signInWithEmailAndPassword(email: email, password: password); if (credential.user != null) { user = credential.user!; _listenForEntries(); } else { print('no user!'); } } // ...
现在运行应用。它应如下所示:
7. 将数据导入模拟器
Firebase 模拟器支持导入和导出数据。通过使用导入和导出,您可以在开发暂停后继续执行开发,使用相同的数据继续开发。您还可以将数据文件提交到 Git,与您合作的其他开发者也可以使用相同的数据。
导出模拟器数据
首先,导出已有的模拟器数据。在模拟器仍在运行时,打开一个新的终端窗口,然后输入以下命令:
firebase emulators:export ./emulators_data
.emulators_data
是一个参数,用于告知 Firebase 导出数据的位置。如果该目录不存在,系统会创建一个。您可以为该目录使用您喜欢的任何名称。
运行此命令后,您会在运行此命令的终端中看到以下输出:
i Found running emulator hub for project flutter-firebase-codelab-d6b79 at http://localhost:4400 i Creating export directory /Users/ewindmill/Repos/codelabs/firebase-emulator-suite/complete/emulators_data i Exporting data to: /Users/ewindmill/Repos/codelabs/firebase-emulator-suite/complete/emulators_data ✔ Export complete
如果您切换到运行模拟器的终端窗口,将会看到以下输出:
i emulators: Received export request. Exporting data to /Users/ewindmill/Repos/codelabs/firebase-emulator-suite/complete/emulators_data. ✔ emulators: Export complete.
最后,如果查看项目目录,您应该会看到一个名为 ./emulators_data
的目录,其中包含 JSON
文件和其他元数据文件,以及您已保存的数据。
导入模拟器数据
现在,您可以在开发工作流中导入这些数据,并从上次停下的地方继续。
首先,在终端中按 CTRL+C
以停止正在运行的模拟器。
接下来,运行您之前看到的 emulators:start
命令,但这次使用一个标志来指示它要导入哪些数据:
firebase emulators:start --import ./emulators_data
模拟器启动后,前往位于 localhost:4000
的模拟器界面,您应该会看到与之前使用的相同数据。
关闭模拟器时自动导出数据
您还可以在退出模拟器时自动导出数据,无需在每次开发会话结束时导出数据。
启动模拟器时,请运行 emulators:start
命令并添加两个额外的标志。
firebase emulators:start --import ./emulators_data --export-on-exit
瞧!现在,每当您为此项目使用模拟器时,系统都会保存并重新加载您的数据。您还可以指定其他目录作为 –export-on-exit flag
的参数,但该目录默认为传递给 –import
的目录。
您还可以使用这些选项的任意组合。以下是文档备注:可以使用 firebase emulators:start --export-on-exit=./saved-data
标志指定导出目录。如果使用 --import
,则导出路径默认为相同;例如:firebase emulators:start --import=./data-path --export-on-exit
。最后,如果需要,将不同的目录路径传递给 --import
和 --export-on-exit
标志。
8. 恭喜!
您已完成 Firebase 模拟器和 Flutter 的使用入门。您可以在 GitHub 上的“complete”目录中找到此 Codelab 完成后的代码:Flutter Codelab
所学内容
- 设置 Flutter 应用以使用 Firebase
- 设置 Firebase 项目
- FlutterFire CLI
- Firebase CLI
- Firebase Authentication 模拟器
- Firebase Firestore 模拟器
- 导入和导出模拟器数据
后续步骤
- 详细了解如何在 Flutter 中使用 Firestore 和 Authentication:了解“将 Firebase 用于 Flutter”Codelab
- 探索提供模拟器的其他 Firebase 工具:
- Cloud Storage
- Cloud Functions
- Realtime Database
- 探索 FlutterFire 界面,以向您的应用快速添加 Google Authentication。
了解详情
- Firebase 网站:firebase.google.com
- Flutter 网站:flutter.dev
- FlutterFire Firebase Flutter widget:firebase.flutter.dev
- Firebase YouTube 频道
- Flutter YouTube 频道
Sparky 为你感到骄傲!