Desenvolvimento local de apps Flutter usando o Pacote de emuladores do Firebase

1. Antes de começar

Neste codelab, você vai aprender a usar o Pacote de emuladores do Firebase com o Flutter durante o desenvolvimento local. Você vai aprender a usar a autenticação por e-mail e senha pelo pacote do emulador e a ler e gravar dados no emulador do Firestore. Por fim, você vai importar e exportar dados dos emuladores para trabalhar com os mesmos dados fictícios sempre que retornar ao desenvolvimento.

Pré-requisitos

Este codelab presume que você tem alguma experiência com o Flutter. Caso contrário, talvez você queira primeiro aprender o básico. Confira alguns links úteis:

Você também precisa ter alguma experiência com o Firebase, mas não precisa ter adicionado o Firebase a um projeto do Flutter. Se você não conhece o Console do Firebase ou é novo no Firebase, consulte os links a seguir:

O que você vai criar

Este codelab orienta você na criação de um aplicativo simples de Registro no Diário. O aplicativo terá uma tela de login e uma tela que permite ler as entradas anteriores do diário e criar novas.

cd5c4753bbee8af.png 8cb4d21f656540bf.png

O que você vai aprender

Você vai aprender a começar a usar o Firebase e a integrar e usar o conjunto de emuladores do Firebase no seu fluxo de trabalho de desenvolvimento do Flutter. Estes tópicos do Firebase serão abordados:

Esses tópicos são abordados na medida do necessário para abranger o pacote de emuladores do Firebase. Este codelab se concentra na adição de um projeto do Firebase ao seu app Flutter e no desenvolvimento usando o Conjunto de emuladores do Firebase. Não haverá discussões detalhadas sobre o Firebase Authentication ou o Firestore. Se você não estiver familiarizado com esses tópicos, recomendamos começar com o codelab Introdução ao Firebase para Flutter.

Pré-requisitos

  • Conhecimento prático do Flutter e do SDK instalado.
  • Editores de texto Intellij JetBrains ou VS Code
  • Navegador Google Chrome (ou outra plataforma de desenvolvimento preferida para o Flutter. Alguns comandos do terminal neste codelab vão presumir que o app está sendo executado no Chrome.

2. Criar e configurar um projeto do Firebase

A primeira tarefa que você precisa concluir é criar um projeto do Firebase no console da Web do Firebase. A maior parte deste codelab se concentra no Pacote de emuladores, que usa uma interface executada localmente, mas primeiro é necessário configurar um projeto completo do Firebase.

Criar um projeto do Firebase

  1. Faça login no console do Firebase.
  2. No Console do Firebase, clique em Adicionar projeto (ou Criar um projeto) e insira um nome para o projeto do Firebase (por exemplo, Firebase-Flutter-Codelab).

fe6aeab3b91965ed.png

  1. Clique nas opções de criação de projeto. Se for solicitado, aceite os termos do Firebase. Ignore a configuração do Google Analytics, porque você não vai usá-lo para este app.

d1fcec48bf251eaa.png

Para saber mais sobre os projetos do Firebase, consulte Noções básicas sobre projetos do Firebase.

O app que você está criando usa dois produtos do Firebase disponíveis para apps Flutter:

  • Firebase Authentication para permitir que os usuários façam login no app.
  • Cloud Firestore para salvar dados estruturados na nuvem e receber notificações instantâneas quando os dados são alterados.

Esses dois produtos precisam de configuração especial ou precisam ser ativados usando o Console do Firebase.

Ativar o Cloud Firestore

O app Flutter usa o Cloud Firestore para salvar entradas de diário.

Ative o Cloud Firestore:

  1. Na seção Build do Console do Firebase, clique em Cloud Firestore.
  2. Clique em Criar banco de dados. 99e8429832d23fa3.png
  3. Selecione a opção Iniciar no modo de teste. Leia a exoneração de responsabilidade sobre as regras de segurança. O modo de teste garante que você possa gravar livremente no banco de dados durante o desenvolvimento. Clique em Próxima. 6be00e26c72ea032.png
  4. Selecione o local para salvar seu banco de dados ou use o padrão. Esse local não pode ser modificado mais tarde. 278656eefcfb0216.png
  5. Clique em Ativar.

3. Configurar o app Flutter

Você vai precisar fazer o download do código inicial e instalar a CLI do Firebase antes de começar.

Acessar o código inicial

Clone o repositório do GitHub (link em inglês) na linha de comando:

git clone https://github.com/flutter/codelabs.git flutter-codelabs

Como alternativa, se você tiver a ferramenta CLI do GitHub instalada:

gh repo clone flutter/codelabs flutter-codelabs

O exemplo de código precisa ser clonado para o diretório flutter-codelabs, que contém o código de uma coleção de codelabs. O código deste codelab está em flutter-codelabs/firebase-emulator-suite.

A estrutura de diretórios em flutter-codelabs/firebase-emulator-suite consiste em dois projetos do Flutter. Uma delas é chamada complete, que pode ser usada para pular para a frente ou fazer uma referência cruzada do seu próprio código. O outro projeto tem o nome start.

O código que você quer usar está no diretório flutter-codelabs/firebase-emulator-suite/start. Abra ou importe esse diretório para o ambiente de desenvolvimento integrado de sua preferência.

cd flutter-codelabs/firebase-emulator-suite/start

Instalar a CLI do Firebase

A CLI do Firebase oferece ferramentas para gerenciar seus projetos do Firebase. A CLI é necessária para usar o Pacote de emuladores. Portanto, será preciso instalá-lo.

Há várias maneiras de instalar a CLI. Se você estiver usando o MacOS ou o Linux, a maneira mais simples é executar este comando no seu terminal:

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

Depois de instalar a CLI, você precisa fazer a autenticação com o Firebase.

  1. Faça login no Firebase com sua Conta do Google executando o seguinte comando:
firebase login
  1. Esse comando conecta sua máquina local ao Firebase e concede acesso aos seus projetos do Firebase.
  1. Para testar se a CLI está instalada corretamente e tem acesso à sua conta, liste seus projetos do Firebase. Execute este comando:
firebase projects:list
  1. A lista exibida precisa conter os mesmos projetos que aparecem no Console do Firebase. Pelo menos será exibido firebase-flutter-codelab.

Instalar a CLI do FlutterFire

A CLI do FlutterFire foi criada com base na CLI do Firebase e facilita a integração de um projeto do Firebase com seu app do Flutter.

Primeiro, instale a CLI:

dart pub global activate flutterfire_cli

Verifique se a CLI foi instalada. Execute o comando a seguir no diretório do projeto do Flutter e verifique se a CLI gera o menu de ajuda.

flutterfire --help

Usar a CLI do Firebase e a CLI do FlutterFire para adicionar o projeto do Firebase ao app Flutter

Com as duas CLIs instaladas, é possível configurar produtos individuais do Firebase (como o Firestore), fazer o download de emuladores e adicionar o Firebase ao app Flutter com apenas alguns comandos do terminal.

Primeiro, conclua a configuração do Firebase executando o seguinte comando:

firebase init

Esse comando conduzirá você por uma série de perguntas necessárias para configurar seu projeto. Estas capturas de tela mostram o fluxo:

  1. Quando solicitado a selecionar recursos, selecione "Firestore" e "Emuladores". Não há uma opção de autenticação, porque ela não usa uma configuração que possa ser modificada nos arquivos do projeto do Flutter. fe6401d769be8f53.png
  2. Em seguida, selecione "Usar um projeto existente" quando solicitado.

f11dcab439e6ac1e.png

  1. Agora, selecione o projeto que você criou em uma etapa anterior: flutter-firebase-codelab.

3bdc0c6934991c25.png

  1. Em seguida, você receberá uma série de perguntas sobre como nomear os arquivos que serão gerados. Sugiro pressionar "Enter" em cada pergunta para selecionar o padrão. 9bfa2d507e199c59.png
  2. Por fim, você vai precisar configurar os emuladores. Selecione "Firestore e Authentication" na lista e pressione Enter. a cada pergunta sobre as portas específicas a serem usadas para cada emulador. Selecione o padrão "Sim" quando for perguntado se você quer usar a interface do emulador.

No final do processo, você verá uma saída semelhante à captura de tela abaixo.

Importante: sua saída pode ser um pouco diferente da minha, como mostrado na captura de tela abaixo, porque a pergunta final será "Não" por padrão se você já tiver feito o download dos emuladores.

8544e41037637b07.png

Configurar o FlutterFire

Em seguida, use o FlutterFire para gerar o código Dart necessário para usar o Firebase no seu app Flutter.

flutterfire configure

Quando esse comando for executado, você precisará selecionar qual projeto do Firebase quer usar e quais plataformas quer configurar. Neste codelab, os exemplos usam o Flutter Web, mas é possível configurar seu projeto do Firebase para usar todas as opções.

As capturas de tela a seguir mostram as solicitações que você precisa responder.

619b7aca6dc15472.png 301c9534f594f472.png

Esta captura de tela mostra a saída no final do processo. Se você já conhece o Firebase, vai perceber que não precisou criar aplicativos no console, e a CLI do FlutterFire fez isso por você.

12199a85ade30459.png

Adicionar pacotes do Firebase ao app Flutter

A etapa final de configuração é adicionar os pacotes relevantes do Firebase ao seu projeto do Flutter. No terminal, verifique se você está na raiz do projeto do Flutter em flutter-codelabs/firebase-emulator-suite/start. Em seguida, execute os três comandos a seguir:

flutter pub add firebase_core
flutter pub add firebase_auth
flutter pub add cloud_firestore

Estes são os únicos pacotes que você vai usar neste aplicativo.

4. Como ativar os emuladores do Firebase

Até agora, o app Flutter e seu projeto do Firebase estão configurados para usar os emuladores, mas você ainda precisa instruir o código do Flutter a redirecionar as solicitações de saída do Firebase para as portas locais.

Primeiro, adicione o código de inicialização do Firebase e o código de configuração do emulador à função main em main.dart.

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());
}

As primeiras linhas de código inicializam o Firebase. Quase universalmente, se você está trabalhando com o Firebase em um app Flutter, convém começar chamando WidgetsFlutterBinding.ensureInitialized e Firebase.initializeApp.

Em seguida, o código que começa com a linha if (kDebugMode) instrui o app a segmentar os emuladores em vez de um projeto de produção do Firebase. kDebugMode garante que o direcionamento para os emuladores aconteça apenas se você estiver em um ambiente de desenvolvimento. Como kDebugMode é um valor constante, o compilador Dart sabe que precisa remover esse bloco de código completamente no modo de lançamento.

Iniciar os emuladores

Inicie os emuladores antes de iniciar o app Flutter. Primeiro, inicie os emuladores executando o seguinte comando no terminal:

firebase emulators:start

Esse comando inicializa os emuladores e expõe as portas localhost com que podemos interagir. Ao executar esse comando, você verá uma resposta semelhante a esta:

bb7181eb70829606.png

Essa saída informa quais emuladores estão em execução e onde você pode acessá-los. Primeiro, confira a interface do emulador em localhost:4000.

11563f4c7216de81.png

Esta é a página inicial da interface do emulador local. Ele lista todos os emuladores disponíveis, e cada um deles é rotulado com o status ativado ou desativado.

5. O emulador do Firebase Auth

O primeiro emulador que você vai usar é o Authentication. Comece com o emulador do Auth clicando em "Go to emulator" no card "Autenticação" da interface. Será exibida uma página como esta:

3c1bfded40733189.png

Esta página é parecida com a do console da Web do Auth. Ela tem uma tabela que lista os usuários, assim como o console on-line, e permite adicionar usuários manualmente. Uma grande diferença aqui é que a única opção de método de autenticação disponível nos emuladores é por e-mail e senha. Isso é suficiente para o desenvolvimento local.

Em seguida, você vai aprender a adicionar um usuário ao emulador do Firebase Auth e fazer login nesse usuário pela interface do Flutter.

Adicionar um usuário

Clique no botão "Adicionar usuário" e preencha o formulário com estas informações:

  • Nome de exibição: Dash
  • E-mail: traço@e-mail.com
  • Senha: palavra-chave

Envie o formulário e você vai notar que a tabela agora inclui um usuário. Agora você pode atualizar o código para fazer login com esse usuário.

logged_out_view.dart

O único código no widget LoggedOutView que precisa ser atualizado está no callback acionado quando um usuário pressiona o botão de login. Atualize o código para que ele fique assim:

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'),
          ),
        ),
      ],
    ),
   ),
  );
 }
}

O código atualizado substitui as strings TODO pelo e-mail e a senha que você criou no emulador de autenticação. Na próxima linha, a linha if(true) foi substituída por um código que verifica se state.user é nulo. O código em AppClass esclarece melhor isso.

app_state.dart (link em inglês)

Duas partes do código em AppState precisam ser atualizadas. Primeiro, atribua ao membro da classe AppState.user o tipo User do pacote firebase_auth, em vez do tipo Object.

Depois, preencha o método AppState.login como mostrado abaixo:

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!');
   }
 } 
 // ...
}

A definição de tipo do usuário agora é User?. A classe User vem do Firebase Auth e fornece as informações necessárias, como User.displayName, que serão discutidas mais adiante.

Este é o código básico necessário para fazer login de um usuário com e-mail e senha no Firebase Auth. Ele faz uma chamada para o FirebaseAuth para fazer login, o que retorna um objeto Future<UserCredential>. Quando o futuro for concluído, esse código vai verificar se há um User anexado ao UserCredential. Se houver um usuário no objeto da credencial, significa que ele fez login e a propriedade AppState.user pode ser definida. Se não houver, significa que houve um erro e ele será exibido.

A única linha de código neste método que é específica para este app (em vez do código geral do FirebaseAuth) é a chamada para o método _listenForEntries, que será abordada na próxima etapa.

TODO: Action Icon – Reload your app, and then press the Login button when it renders. Isso faz com que o app navegue até uma página que diz "Welcome Back, Person!" na parte superior. A autenticação está funcionando, porque você conseguiu acessar esta página, mas uma pequena atualização precisa ser feita em logged_in_view.dart para mostrar o nome real do usuário.

logged_in_view.dart (link em inglês)

Mude a primeira linha no método 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(
 // ...

Agora, essa linha extrai o displayName da propriedade User no objeto AppState. Esse displayName foi definido no emulador quando você definiu seu primeiro usuário. Agora, seu app exibirá "Welcome back, Dash!". quando você fizer login, em vez de TODO.

6. Ler e gravar dados no emulador do Firestore

Primeiro, confira o emulador do Firestore. Na página inicial da interface do emulador (localhost:4000), clique em "Acessar emulador" no card do Firestore. Ele será parecido com o seguinte:

Emulador:

791fce7dc137910a.png

Console do Firebase:

e0dde9aea34af050.png

Se você já usou o Firestore, vai notar que essa página é semelhante à página do Firestore no console do Firebase. No entanto, há algumas diferenças notáveis.

  1. É possível limpar todos os dados com um toque em um botão. Isso seria perigoso com dados de produção, mas é útil para iterações rápidas. Se você estiver trabalhando em um novo projeto e seu modelo de dados mudar, é fácil limpar.
  2. Há um campo "Solicitações" . Essa guia permite acompanhar as solicitações recebidas feitas no emulador. Falaremos sobre essa guia em mais detalhes em breve.
  3. Não há guias para Regras, Índices ou Uso. Há uma ferramenta (discutida na próxima seção) que ajuda a escrever regras de segurança, mas não é possível defini-las para o emulador local.

Para resumir essa lista, esta versão do Firestore oferece mais ferramentas úteis durante o desenvolvimento e remove as ferramentas que são necessárias na produção.

Gravar no Firestore

Antes de discutir as "Solicitações" no emulador, primeiro faça uma solicitação. Isso exige atualizações de código. Comece conectando o formulário no app para gravar um novo diário Entry no Firestore.

O fluxo geral para enviar um Entry é o seguinte:

  1. O usuário preencheu o formulário e pressionou o botão Submit
  2. A interface chama AppState.writeEntryToFirebase
  3. AppState.writeEntryToFirebase adiciona uma entrada ao Firebase.

Nenhum código envolvido na etapa 1 ou 2 precisa ser alterado. O único código que precisa ser adicionado na etapa 3 será incluído na classe AppState. Faça a seguinte mudança em 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,
   });
 }
 // ...
}

O código no método writeEntryToFirebase extrai uma referência à coleção chamada "Entries" no Firestore. Em seguida, ele adiciona uma nova entrada, que precisa ser do tipo Map<String, String>.

Nesse caso, a coleção "Entries" no Firestore não existia, então ele criou uma.

Com esse código adicionado, faça o Hot Reload ou reinicie o app, faça login e navegue até a visualização EntryForm. Você pode preencher o formulário com qualquer Strings que quiser. O campo "Date" aceita qualquer string, como foi simplificado neste codelab. Ele não tem uma validação forte nem se importa com objetos DateTime.

Pressione "Enviar" no formulário. Nada acontecerá no app, mas você poderá conferir a nova entrada na interface do emulador.

A guia "Solicitações" no emulador do Firestore

Na interface, navegue até o emulador do Firestore e procure a opção "Data". . Agora há uma coleção na raiz do banco de dados chamada "Entradas". Ele deve ter um documento com as mesmas informações que você inseriu no formulário.

a978fb34fb8a83da.png

Isso confirma que o AppState.writeEntryToFirestore funcionou. Agora é possível analisar melhor a solicitação na guia "Solicitações". Clique nessa guia agora.

Solicitações do emulador do Firestore

Você vai encontrar uma lista parecida com esta:

f0b37f0341639035.png

Você pode clicar em qualquer um desses itens da lista e ver muitas informações úteis. Clique no item da lista CREATE que corresponde à sua solicitação para criar uma nova entrada no diário. Você verá uma nova tabela como esta:

385d62152e99aad4.png

Como mencionado, o emulador do Firestore oferece ferramentas para desenvolver as regras de segurança do seu app. Essa visualização mostra exatamente qual linha nas suas regras de segurança foi aprovada (ou falhou, se esse for o caso). Em um app mais robusto, as regras de segurança podem crescer e ter várias verificações de autorização. Essa visualização é usada para ajudar a escrever e depurar essas regras de autorização.

Ele também oferece uma maneira fácil de inspecionar cada parte dessa solicitação, incluindo os metadados e os dados de autenticação. Esses dados são usados para escrever regras de autorização complexas.

Como ler do Firestore

O Firestore usa sincronização para enviar dados atualizados para os dispositivos conectados. No código do Flutter, é possível detectar (ou assinar) coleções e documentos do Firestore, e o código vai receber uma notificação sempre que os dados mudarem. Neste app, a detecção de atualizações do Firestore é feita no método AppState._listenForEntries.

Esse código funciona com StreamController e Stream, chamados AppState._entriesStreamController e AppState.entries, respectivamente. Esse código já está escrito, assim como todo o código necessário na interface para exibir os dados do Firestore.

Atualize o método _listenForEntries para corresponder ao código abaixo:

app_state.dart (link em inglês)

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);
   });
 }
 // ...
}

Esse código ouve as "Entradas" no Firestore. Quando o Firestore notifica o cliente de que há novos dados, ele transmite esses dados, e o código em _listenForEntries muda todos os documentos filhos para um objeto que o app pode usar (Entry). Em seguida, ele adiciona essas entradas ao StreamController chamado _entriesStreamController (que a interface está detectando). Esse código é a única atualização necessária.

Por fim, lembre-se de que o método AppState.logIn faz uma chamada para _listenForEntries, que inicia o processo de detecção depois que um usuário faz login.

// ...
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!');
 }
}
// ...

Agora, execute o app. O código vai ficar assim:

b8a31c7a8900331.gif

7. Exportar e importar dados para o emulador

Os emuladores do Firebase oferecem suporte à importação e exportação de dados. Com o uso de importações e exportações, é possível continuar o desenvolvimento com os mesmos dados quando você fizer uma pausa no desenvolvimento e, em seguida, retomar. Você também pode fazer commit de arquivos de dados no git, e outros desenvolvedores com quem você estiver trabalhando terão os mesmos dados para trabalhar.

Exportar dados do emulador

Primeiro, exporte os dados do emulador que você já tem. Enquanto os emuladores ainda estiverem em execução, abra uma nova janela do terminal e digite o seguinte comando:

firebase emulators:export ./emulators_data

.emulators_data é um argumento, que informa ao Firebase para onde exportar os dados. Se o diretório não existir, ele será criado. Você pode usar o nome que quiser para o diretório.

Ao executar o comando, você vai encontrar esta resposta no terminal em que o comando foi executado:

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

Se você alternar para a janela do terminal em que os emuladores estão em execução, vai ver esta saída:

i  emulators: Received export request. Exporting data to /Users/ewindmill/Repos/codelabs/firebase-emulator-suite/complete/emulators_data.
✔  emulators: Export complete.

Por fim, se você procurar no diretório do projeto, vai encontrar um diretório chamado ./emulators_data, que contém arquivos JSON, entre outros arquivos de metadados, com os dados salvos.

Importar dados do emulador

Agora é possível importar esses dados como parte do seu fluxo de trabalho de desenvolvimento e começar de onde parou.

Primeiro, interrompa os emuladores, se estiverem em execução, pressionando CTRL+C no terminal.

Em seguida, execute o comando emulators:start que você já conhece, mas com uma flag informando quais dados importar:

firebase emulators:start --import ./emulators_data

Quando os emuladores estiverem ativos, navegue até a interface do emulador em localhost:4000 para ver os mesmos dados usados anteriormente.

Exportar dados automaticamente ao fechar emuladores

Também é possível exportar dados automaticamente ao sair dos emuladores, em vez de lembrar de exportar os dados ao final de cada sessão de desenvolvimento.

Ao iniciar os emuladores, execute o comando emulators:start com duas outras sinalizações.

firebase emulators:start --import ./emulators_data --export-on-exit

Pronto! Seus dados serão salvos e atualizados sempre que você trabalhar com os emuladores deste projeto. Também é possível especificar um diretório diferente como um argumento para o –export-on-exit flag, mas ele será padrão para o diretório transmitido para –import.

Também é possível usar qualquer combinação dessas opções. Esta é a nota dos documentos: o diretório de exportação pode ser especificado com esta sinalização: firebase emulators:start --export-on-exit=./saved-data. Se --import for usado, o caminho de exportação será o mesmo, por exemplo: firebase emulators:start --import=./data-path --export-on-exit. Por fim, se desejar, transmita caminhos de diretório diferentes para as flags --import e --export-on-exit.

8. Parabéns!

Você concluiu a seção "Começar a usar o emulador do Firebase e o Flutter". O código completo deste codelab está disponível no diretório "complete" no GitHub: Flutter Codelabs.

O que vimos

  • Como configurar um app Flutter para usar o Firebase
  • Como configurar um projeto do Firebase
  • CLI do FlutterFire
  • CLI do Firebase
  • Emulador do Firebase Authentication
  • Emulador do Firebase Firestore
  • Como importar e exportar dados do emulador

Próximas etapas

Saiba mais

O Sparky está orgulhoso de você!

2a0ad195769368b1.gif