使用 Firebase Emulator Suite 针对 Flutter 应用进行本地开发

1. 准备工作

在此 Codelab 中,您将了解如何在本地开发期间将 Firebase Emulator Suite 与 Flutter 搭配使用。您将学习如何通过 Emulator Suite 使用电子邮件地址-密码身份验证,以及如何向 Firestore 模拟器读取和写入数据。最后,您将学习如何从模拟器导入和导出数据,以便每次返回开发环境时都能使用相同的伪造数据。

前提条件

此 Codelab 假定您具有一些 Flutter 经验。如果没有,您可能需要先了解基础知识。以下链接非常有用:

您还应具备一定的 Firebase 经验,但即使您从未将 Firebase 添加到 Flutter 项目中,也没关系。如果您不熟悉 Firebase 控制台,或者完全不了解 Firebase,请先参阅以下链接:

您将创建的内容

此 Codelab 将引导您构建一个简单的日记应用。该应用将包含一个登录界面,以及一个可供您阅读过往日记条目和创建新条目的界面。

cd5c4753bbee8af.png 8cb4d21f656540bf.png

学习内容

您将学习如何开始使用 Firebase,以及如何将 Firebase Emulator Suite 集成到 Flutter 开发工作流中并使用它。我们将介绍以下 Firebase 主题:

请注意,这些主题的涵盖范围仅限于 Firebase 模拟器套件所需的内容。此 Codelab 重点介绍如何将 Firebase 项目添加到 Flutter 应用,以及如何使用 Firebase Emulator Suite 进行开发。本文不会深入探讨 Firebase Authentication 或 Firestore。如果您不熟悉这些主题,建议您先学习了解如何将 Firebase 用于 Flutter Codelab

您需要满足的条件

  • 具备 Flutter 的实操知识,并已安装 SDK
  • Intellij JetBrains 或 VS Code 文本编辑器
  • Google Chrome 浏览器(或您为 Flutter 选择的其他首选开发目标平台)。本 Codelab 中的一些终端命令会假设您是在 Chrome 上运行应用)

2. 创建和设置 Firebase 项目

您需要完成的第一个任务是在 Firebase 的 Web 控制台中创建一个 Firebase 项目。此 Codelab 的绝大部分内容都将侧重于使用本地运行的界面的 Emulator Suite,但您必须先设置完整的 Firebase 项目。

创建 Firebase 项目

  1. 使用您的 Google 账号登录 Firebase 控制台
  2. 点击相应按钮以创建新项目,然后输入项目名称(例如 Firebase-Flutter-Codelab)。
  3. 点击继续
  4. 如果看到相关提示,请查看并接受 Firebase 条款,然后点击继续
  5. (可选)在 Firebase 控制台中启用 AI 辅助功能(称为“Gemini in Firebase”)。
  6. 在此 Codelab 中,您不需要使用 Google Analytics,因此请关闭 Google Analytics 选项。
  7. 点击创建项目,等待项目完成预配,然后点击继续

如需详细了解 Firebase 项目,请参阅了解 Firebase 项目

设置 Firebase 产品

您所构建的应用会使用两个适用于 Flutter 应用的 Firebase 产品:

  • Firebase Authentication,可让用户登录您的应用。
  • Cloud Firestore:用于在云端保存结构化数据,并在数据发生变化时即时收到通知。

这两款产品需要进行特殊配置,或需要使用 Firebase 控制台启用。

启用 Cloud Firestore

Flutter 应用使用 Cloud Firestore 保存日记条目。

启用 Cloud Firestore:

  1. 在 Firebase 控制台的构建部分中,点击 Cloud Firestore
  2. 点击 Create database99e8429832d23fa3.png
  3. 选择以测试模式开始选项。阅读有关安全规则的免责声明。测试模式可确保您在开发过程中可以随意向数据库写入数据。点击下一步6be00e26c72ea032.png
  4. 选择数据库的位置(只需使用默认值即可)。请注意,此位置以后无法更改。278656eefcfb0216.png
  5. 点击启用

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 进行身份验证。

  1. 运行以下命令,使用您的 Google 账号登录 Firebase:
firebase login
  1. 此命令将您的本地机器与 Firebase 关联,并授予您对 Firebase 项目的访问权限。
  1. 通过列出 Firebase 项目来测试 CLI 是否已正确安装,以及是否能访问您的账号。运行以下命令:
firebase projects:list
  1. 显示的列表应与 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

此命令会引导您完成设置项目所需的一系列问题。以下屏幕截图显示了相应流程:

  1. 当系统提示您选择功能时,请选择“Firestore”和“模拟器”。(没有“身份验证”选项,因为它不使用可从 Flutter 项目文件修改的配置。)fe6401d769be8f53.png
  2. 接下来,在出现提示时选择“使用现有项目”。

f11dcab439e6ac1e.png

  1. 现在,选择您在上一步中创建的项目:flutter-firebase-codelab。

3bdc0c6934991c25.png

  1. 接下来,系统会询问您一系列有关命名将生成的文件的问题。建议您针对每个问题按“Enter”键以选择默认值。9bfa2d507e199c59.png
  2. 最后,您需要配置模拟器。从列表中选择 Firestore 和 Authentication,然后针对有关每个模拟器要使用的特定端口的每个问题按“Enter”键。当系统询问您是否要使用模拟器界面时,您应选择默认选项“是”。

流程结束时,您应该会看到类似于以下屏幕截图的输出。

重要提示:您的输出可能与我的略有不同,如下面的屏幕截图所示,因为如果您已下载模拟器,则最终问题的默认答案将为“否”。

8544e41037637b07.png

配置 FlutterFire

接下来,您可以使用 FlutterFire 生成所需的 Dart 代码,以便在 Flutter 应用中使用 Firebase。

flutterfire configure

运行此命令后,系统会提示您选择要使用的 Firebase 项目以及要设置的平台。在此 Codelab 中,示例使用 Flutter Web,但您可以设置 Firebase 项目以使用所有选项。

以下屏幕截图显示了您需要回答的提示。

619b7aca6dc15472.png 301c9534f594f472.png

此屏幕截图显示了流程结束时的输出。如果您熟悉 Firebase,就会发现您不必在控制台中创建应用,FlutterFire CLI 会为您完成此操作。

12199a85ade30459.png

将 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.ensureInitializedFirebase.initializeApp

之后,以 if (kDebugMode) 开头的代码会指示您的应用以模拟器为目标,而不是以正式版 Firebase 项目为目标。kDebugMode 可确保仅当您处于开发环境中时,才会定位到模拟器。由于 kDebugMode 是一个常量值,因此 Dart 编译器知道在发布模式下完全移除该代码块。

启动模拟器

您应先启动模拟器,然后再启动 Flutter 应用。首先,在终端中运行以下命令来启动模拟器:

firebase emulators:start

此命令会启动模拟器,并公开可用于与之互动的本地主机端口。运行该命令后,您应该会看到类似如下所示的输出:

bb7181eb70829606.png

此输出会告知您哪些模拟器正在运行,以及您可以在哪里查看这些模拟器。首先,请查看 localhost:4000 中的模拟器界面。

11563f4c7216de81.png

这是本地模拟器界面的首页。它会列出所有可用的模拟器,并为每个模拟器标记启用或停用状态。

5. Firebase Auth 模拟器

您将使用的第一个模拟器是 Authentication 模拟器。首先,点击界面中“身份验证”卡片上的“前往模拟器”,启动身份验证模拟器,然后您会看到如下所示的页面:

3c1bfded40733189.png

此页面与身份验证 Web 控制台页面类似。它包含一个列出用户的表格(与在线控制台类似),并允许您手动添加用户。一个很大的区别是,模拟器上唯一可用的身份验证方法选项是通过电子邮件地址和密码进行身份验证。这足以满足本地开发需求。

接下来,您将逐步了解如何将用户添加到 Firebase Auth 模拟器,然后通过 Flutter 界面登录该用户。

添加用户

点击“添加用户”按钮,然后填写包含以下信息的表单:

  • 显示名称:Dash
  • 电子邮件地址:dash@email.com
  • 密码:dashword

提交表单后,您会看到表格现在包含一个用户。现在,您可以更新代码以使用该用户登录。

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 Auth,可提供所需的信息,例如 User.displayName(稍后会讨论)。

这是在 Firebase Authentication 中使用电子邮件地址和密码登录用户所需的基本代码。它会调用 FirebaseAuth 进行登录,并返回一个 Future<UserCredential> 对象。当 future 完成时,此代码会检查 UserCredential 是否附加了 User。如果凭据对象中存在用户,则表示用户已成功登录,并且可以设置 AppState.user 属性。如果没有,则表示出现了错误,并会打印出来。

请注意,此方法中唯一特定于此应用(而非常规 FirebaseAuth 代码)的代码行是对 _listenForEntries 方法的调用,我们将在下一步中介绍此方法。

待办事项:操作图标 - 重新加载应用,然后在应用呈现时按“登录”按钮。这会导致应用导航到顶部显示“欢迎回来,用户!”的页面。身份验证必须正常运行,因为您已能够前往此页面,但需要对 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 卡片上的“前往模拟器”。它应如下所示:

模拟器:

791fce7dc137910a.png

Firebase 控制台:

e0dde9aea34af050.png

如果您有使用 Firestore 的经验,就会发现此页面与 Firebase 控制台的 Firestore 页面非常相似。不过,两者之间存在一些显著差异。

  1. 只需点按一个按钮,即可清除所有数据。这对于生产数据来说很危险,但有助于快速迭代!如果您正在处理新项目,并且数据模型发生了变化,可以轻松清除。
  2. 有“请求”标签页。通过此标签页,您可以查看向此模拟器发出的传入请求。稍后,我将详细介绍此标签页。
  3. 没有“规则”“索引”或“使用情况”标签页。虽然有一个工具(将在下一部分中讨论)可帮助您编写安全规则,但您无法为本地模拟器设置安全规则。

总而言之,此版本的 Firestore 提供了更多在开发期间有用的工具,并移除了生产环境中需要的工具。

写入到 Firestore

在讨论模拟器中的“请求”标签页之前,请先发出请求。这需要更新代码。首先,将应用中的表单连接起来,以将新日记 Entry 写入 Firestore。

提交 Entry 的简要流程如下:

  1. 用户填写表单并按下了 Submit 按钮
  2. 界面调用 AppState.writeEntryToFirebase
  3. 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。(日期字段将接受任何字符串,因为此 Codelab 对其进行了简化。它不具有强验证功能,也不以任何方式关心 DateTime 对象。)

按表单上的“提交”。应用中不会发生任何变化,但您可以在模拟器界面中看到新条目。

Firestore 模拟器中的“请求”标签页

在界面中,前往 Firestore 模拟器,然后查看“数据”标签页。您应该会看到,数据库的根目录下现在有一个名为“Entries”的集合。该文档应包含您在表单中输入的信息。

a978fb34fb8a83da.png

这确认了 AppState.writeEntryToFirestore 正常运行,现在您可以在“请求”标签页中进一步探索该请求。现在点击该标签页。

Firestore 模拟器请求

您应该会看到类似于以下内容的列表:

f0b37f0341639035.png

您可以点击这些列表项中的任意一项,查看大量实用信息。点击与您创建新日记条目的请求对应的 CREATE 列表项。您会看到一个如下所示的新表格:

385d62152e99aad4.png

如上所述,Firestore 模拟器提供了用于开发应用安全规则的工具。此视图会准确显示相应请求通过(或失败,如果适用)了安全规则中的哪一行。在更强大的应用中,安全规则可能会不断增加,并包含多项授权检查。此视图用于帮助编写和调试这些授权规则。

它还提供了一种简单的方法来检查此请求的每个部分,包括元数据和身份验证数据。此数据用于编写复杂的授权规则。

从 Firestore 读取数据

Firestore 使用数据同步功能将更新后的数据推送到已连接的设备。在 Flutter 代码中,您可以监听(或订阅)Firestore 集合和文档,并且您的代码会在数据发生任何更改时收到通知。在此应用中,监听 Firestore 更新是在名为 AppState._listenForEntries 的方法中完成的。

此代码与分别称为 AppState._entriesStreamControllerAppState.entriesStreamControllerStream 配合使用。该代码已编写完成,界面中显示来自 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)。然后,它会将这些条目添加到名为 _entriesStreamControllerStreamController(界面正在监听该对象)。此代码是唯一需要更新的代码。

最后,请注意,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!');
 }
}
// ...

现在运行应用,它应如下所示:

b8a31c7a8900331.gif

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 快速入门”Codelab。您可以在 GitHub 上的“complete”目录中找到此 Codelab 的完整代码:Flutter Codelab

所学内容

  • 设置 Flutter 应用以使用 Firebase
  • 设置 Firebase 项目
  • FlutterFire CLI
  • Firebase CLI
  • Firebase Authentication 模拟器
  • Firebase Firestore 模拟器
  • 导入和导出模拟器数据

后续步骤

了解详情

Sparky 为你感到骄傲!

2a0ad195769368b1.gif