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 com o 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 falsos sempre que voltar 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 tem problema se nunca tiver adicionado o Firebase a um projeto do Flutter. Se você não conhece o console do Firebase ou nunca usou o Firebase, consulte os seguintes links primeiro:

O que você vai criar

Este codelab mostra como criar um aplicativo simples de diário. O aplicativo terá uma tela de login e outra para ler 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 como integrar e usar o Pacote 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 em que são necessários para cobrir o pacote do emulador do Firebase. Este codelab se concentra em adicionar um projeto do Firebase ao seu app Flutter e no desenvolvimento usando o Pacote de emuladores do Firebase. Não haverá discussões detalhadas sobre o Firebase Authentication ou o Firestore. Se você não conhece esses tópicos, recomendamos começar com o codelab Conheça o 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 outro destino de desenvolvimento preferido para o Flutter. Alguns comandos de terminal neste codelab presumem que você está executando o app no Chrome.

2. Criar e configurar um projeto do Firebase

A primeira tarefa é criar um projeto do Firebase no console da Web do Firebase. A grande maioria deste codelab vai se concentrar no Pacote de emuladores, que usa uma interface executada localmente, mas primeiro você precisa configurar um projeto completo do Firebase.

Criar um projeto do Firebase

  1. Faça login no console do Firebase usando sua Conta do Google.
  2. Clique no botão para criar um projeto e insira um nome (por exemplo, Firebase-Flutter-Codelab).
  3. Clique em Continuar.
  4. Se solicitado, leia e aceite os Termos do Firebase e clique em Continuar.
  5. (Opcional) Ative a assistência de IA no console do Firebase (chamada de "Gemini no Firebase").
  6. Neste codelab, você não precisa do Google Analytics. Portanto, desative a opção do Google Analytics.
  7. Clique em Criar projeto, aguarde o provisionamento e clique em Continuar.

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

Configurar produtos 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: usado 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 o aviso 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 do Flutter

Você vai precisar baixar o 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. Um deles é chamado de complete, que você pode consultar se quiser pular para frente ou fazer uma referência cruzada com seu próprio código. O outro projeto é chamado de start.

O código que você quer usar está no diretório flutter-codelabs/firebase-emulator-suite/start. Abra ou importe esse diretório no 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. Por isso, é preciso instalá-la.

Há várias maneiras de instalar a CLI. A maneira mais simples, se você estiver usando macOS ou Linux, é executar este comando no terminal:

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

Depois de instalar a CLI, é necessário 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.
  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. Você vai encontrar pelo menos firebase-flutter-codelab.

Instalar a CLI do FlutterFire

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

Primeiro, instale a CLI:

dart pub global activate flutterfire_cli

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

flutterfire --help

Use a CLI do Firebase e a CLI do FlutterFire para adicionar seu projeto do Firebase ao app Flutter

Com as duas CLIs instaladas, é possível configurar produtos individuais do Firebase (como o Firestore), baixar os 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 vai guiar 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, escolha "Firestore" e "Emuladores". Não há uma opção de autenticação, já que ela não usa uma configuração que pode ser modificada nos arquivos do projeto 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ê vai responder a uma série de perguntas sobre como nomear os arquivos que serão gerados. Recomendamos pressionar "Enter" para cada pergunta e selecionar o padrão. 9bfa2d507e199c59.png
  2. Por fim, você precisará configurar os emuladores. Selecione "Firestore" e "Authentication" na lista e pressione "Enter" em cada pergunta sobre as portas específicas a serem usadas em cada emulador. Selecione a opção padrão "Sim" quando for perguntado se você quer usar a interface do emulador.

No final do processo, você vai encontrar uma saída parecida com a 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á definida como "Não" se você já tiver os emuladores baixados.

8544e41037637b07.png

Configurar o FlutterFire

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

flutterfire configure

Ao executar esse comando, você vai precisar selecionar qual projeto do Firebase quer usar e quais plataformas quer configurar. Neste codelab, os exemplos usam o Flutter Web, mas você pode configurar seu projeto do Firebase para usar todas as opções.

As capturas de tela a seguir mostram os comandos que você precisa responder.

619b7aca6dc15472.png 301c9534f594f472.png

Esta captura de tela mostra a saída no final do processo. Se você conhece o Firebase, vai notar que não foi necessário 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 da 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

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

4. Como ativar os emuladores do Firebase

Até agora, o app Flutter e o projeto do Firebase estão configurados para usar os emuladores, mas ainda é necessário informar ao código do Flutter para 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 sempre, se você estiver trabalhando com o Firebase em um app Flutter, vai querer começar chamando WidgetsFlutterBinding.ensureInitialized e Firebase.initializeApp.

Depois disso, o código que começa com a linha if (kDebugMode) informa ao app para segmentar os emuladores em vez de um projeto de produção do Firebase. kDebugMode garante que a segmentação dos emuladores só aconteça se você estiver em um ambiente de desenvolvimento. Como kDebugMode é um valor constante, o compilador Dart sabe remover todo o bloco de código no modo de lançamento.

Iniciar os emuladores

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

firebase emulators:start

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

bb7181eb70829606.png

Essa saída informa quais emuladores estão em execução e onde você pode encontrá-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 é rotulado com o status ativado ou desativado.

5. O emulador do Firebase Auth

O primeiro emulador que você vai usar é o de autenticação. Comece com o emulador de autenticação clicando em "Acessar emulador" no card "Autenticação" na interface. Uma página como esta vai aparecer:

3c1bfded40733189.png

Esta página é semelhante à página do console da Web de autenticação. Ela tem uma tabela que lista os usuários, como o console on-line, e permite adicionar usuários manualmente. Uma grande diferença é 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 com ele 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: dash@email.com
  • Senha: dashword

Envie o formulário. A tabela agora vai incluir 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 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 explica melhor isso.

app_state.dart

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.

Em seguida, 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 para usuário agora é User?. Essa classe User vem do Firebase Auth e fornece as informações necessárias, como User.displayName, que será abordado em breve.

Este é o código básico necessário para fazer login de um usuário com um e-mail e uma senha no Firebase Auth. Ele faz uma chamada para o FirebaseAuth para fazer login, 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 de credencial, isso significa que um usuário fez login com sucesso, e a propriedade AppState.user pode ser definida. Se não houver, ocorreu um erro, e ele será impresso.

A única linha de código nesse método que é específica para este app (em vez de 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 com a mensagem "Bem-vindo de volta, Pessoa!" na parte de cima. A autenticação precisa estar funcionando, já que permitiu que você navegasse até 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

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 o primeiro usuário. Agora, o app vai mostrar "Bem-vindo de volta, 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 o 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 é parecida com a página do Firestore no Console do Firebase. No entanto, há algumas diferenças importantes.

  1. É possível limpar todos os dados com o toque de um botão. Isso seria perigoso com dados de produção, mas é útil para iteração rápida. Se você estiver trabalhando em um novo projeto e o modelo de dados mudar, será fácil limpar.
  2. Há uma guia "Solicitações". Nela, você pode assistir às solicitações recebidas feitas a esse emulador. Vamos falar mais sobre essa guia 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 definir regras de segurança para o emulador local.

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

Gravar no Firestore

Antes de discutir a guia "Solicitações" no emulador, 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 é:

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

Nenhum dos códigos envolvidos nas etapas 1 ou 2 precisa ser alterado. O único código que precisa ser adicionado para a 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" não existia no Firestore, então o Firestore criou uma.

Com esse código adicionado, faça uma recarga dinâmica ou reinicie o app, faça login e navegue até a visualização EntryForm. Você pode preencher o formulário com o Strings que quiser. O campo "Data" aceita qualquer string, já que foi simplificado para este codelab. Ele não tem validação forte nem se importa com objetos DateTime de forma alguma.

Clique em "Enviar" no formulário. Nada vai acontecer no app, mas você pode 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 confira a guia "Dados". Agora há uma coleção na raiz do banco de dados chamada "Entries". Ele precisa ter um documento com as mesmas informações que você inseriu no formulário.

a978fb34fb8a83da.png

Isso confirma que o AppState.writeEntryToFirestore funcionou. Agora você pode analisar melhor a solicitação na guia "Solicitações". Clique nessa guia agora.

Solicitações do emulador do Firestore

Aqui, você vai encontrar uma lista parecida com esta:

f0b37f0341639035.png

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

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 essa solicitação passou (ou falhou, se 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.

Leitura no Firestore

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

Esse código funciona em conjunto com os 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 mostrar os dados do Firestore.

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

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

Esse código detecta a coleção "Entries" no Firestore. Quando o Firestore notifica esse 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 nosso 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 escuta 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. Ele vai ficar assim:

b8a31c7a8900331.gif

7. Exportar e importar dados para o emulador

Os emuladores do Firebase permitem importar e exportar dados. Usando as importações e exportações, você pode continuar o desenvolvimento com os mesmos dados quando fizer uma pausa e depois retomar. Também é possível fazer commit de arquivos de dados no git, e outros desenvolvedores com quem você está trabalhando terão os mesmos dados.

Exportar dados do emulador

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

firebase emulators:export ./emulators_data

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

Ao executar esse comando, você verá esta saída no terminal:

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ê mudar para a janela do terminal em que os emuladores estão em execução, 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ê olhar 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 continuar de onde parou.

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

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

firebase emulators:start --import ./emulators_data

Quando os emuladores estiverem ativos, navegue até a interface em localhost:4000. Você vai encontrar os mesmos dados com que estava trabalhando antes.

Exportar dados automaticamente ao fechar emuladores

Você também pode exportar dados automaticamente ao sair dos emuladores, em vez de precisar fazer isso no final de cada sessão de desenvolvimento.

Ao iniciar os emuladores, execute o comando emulators:start com duas flags adicionais.

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

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

Também é possível usar uma combinação dessas opções. Esta é a observação da documentação: o diretório de exportação pode ser especificado com esta flag: 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 quiser, transmita caminhos de diretório diferentes para as flags --import e --export-on-exit.

8. Parabéns!

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

O que vimos

  • 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