Desenvolvimento local para 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 de emuladores, além de ler e gravar dados no emulador do Firestore. Por fim, você vai trabalhar com a importação e exportação de dados dos emuladores, para trabalhar com os mesmos dados simulados 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 deve ter alguma experiência com o Firebase, mas não tem problema se você nunca adicionou o Firebase a um projeto Flutter. Se você não conhece o console do Firebase ou é completamente novo no Firebase, primeiro consulte os links a seguir:

O que você vai criar

Este codelab orientará você na criação de um aplicativo simples de registro em diário. O aplicativo terá uma tela de login e uma tela que permite ler registros anteriores e criar novos.

cd5c4753bbee8af.png 8cb4d21f656540bf.png

Conteúdo

Você vai aprender a usar o Firebase, integrar e usar o pacote de emuladores do Firebase no seu fluxo de trabalho de desenvolvimento do Flutter. Os seguintes tópicos do Firebase serão abordados:

Observe que esses tópicos são abordados na medida em que são necessários para abranger o pacote de emuladores do Firebase. O objetivo deste codelab é adicionar um projeto do Firebase ao seu app do Flutter e desenvolver usando o Pacote de emuladores do Firebase. Não haverá discussões detalhadas sobre o Firebase Authentication ou o Firestore. Se você não conhecer esses tópicos, recomendamos começar pelo codelab Introdução ao Firebase para Flutter.

Pré-requisitos

  • Ter conhecimento prático do Flutter e do SDK instalado.
  • Editores de texto do Intellij JetBrains ou do VS Code
  • Navegador Google Chrome ou outra plataforma de desenvolvimento preferencial para o Flutter. Alguns comandos de terminal neste codelab vão supor que você está executando o app no Chrome.

2. Criar e configurar um projeto do Firebase

A primeira tarefa que você precisa realizar é 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 IU executada localmente. No entanto, primeiro você precisa 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 dê um nome a ele (por exemplo, Firebase-Flutter-Codelab").

fe6aeab3b91965ed.png

  1. Clique nas opções de criação do projeto. Se solicitado, aceite os termos do Firebase. Pular a configuração do Google Analytics, porque ele não vai ser usado neste app.

d1fcec48bf251eaa.png

Para saber mais sobre os projetos do Firebase, consulte Noções básicas sobre os 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: 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ções especiais ou 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 do seu banco de dados ou use o padrão. Esse local não pode ser alterado depois. 278656eefcfb0216.png
  5. Selecione Ativar.

3. Configurar o app do Flutter

Antes de começar, faça o download do código inicial e instale a CLI do Firebase.

Acessar o código inicial

Clone o repositório do GitHub (link em inglês) da 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 no 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 é composta por dois projetos do Flutter. Uma delas é chamada de complete, que você pode consultar se quiser avançar ou fazer referência cruzada ao seu código. O outro projeto tem o nome start.

O código com que você quer começar 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, você precisa instalá-lo.

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

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

Depois de instalar a CLI, faça 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. Liste seus projetos do Firebase para testar se a CLI está instalada corretamente e tem acesso à conta. Execute este comando:
firebase projects:list
  1. A lista exibida precisa conter os mesmos projetos do Firebase listados no Console do Firebase. O firebase-flutter-codelab deve aparecer pelo menos.

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 ao 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 seu projeto do Firebase ao app do Flutter

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

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

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, selecione "Firestore" e "Emulators". Não há opção de autenticação, já que ela não usa a configuração que pode ser modificada dos arquivos do projeto do Flutter. fe6401d769be8f53.png
  2. Depois, 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 precisar responder a uma série de perguntas sobre como nomear os arquivos que serão gerados. Sugiro pressionar "Enter" para cada pergunta para selecionar a opção padrão. 9bfa2d507e199c59.png
  2. Por fim, você precisa configurar os emuladores. Selecione Firestore e Authentication na lista e pressione "Enter" para cada pergunta sobre as portas específicas que serão usadas em cada emulador. Selecione o padrão "Yes" quando for perguntado se você quer usar a IU do emulador.

No final do processo, você verá uma saída parecida com a captura de tela a seguir.

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

8544e41037637b07.png

Configurar o FlutterFire

Em seguida, é possível usar o FlutterFire para gerar o código Dart necessário para usar o Firebase no seu app criado com o Flutter.

flutterfire configure

Quando esse comando é executado, você precisa 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 abaixo 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 estiver familiarizado com o Firebase, você perceberá que não era 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 de configuração é adicionar os pacotes relevantes do Firebase ao seu projeto do Flutter. No terminal, verifique se você está na raiz do projeto 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ê usará neste aplicativo.

4. Como ativar os emuladores do Firebase

Até agora, o app Flutter e seu projeto do Firebase estão configurados para poder usar os emuladores, mas você ainda precisa instruir o 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 (link em inglês)

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. De maneira quase universal, se você estiver trabalhando com o Firebase em um app Flutter, comece chamando WidgetsFlutterBinding.ensureInitialized e Firebase.initializeApp.

Depois disso, 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. O kDebugMode garante que o direcionamento aos emuladores só aconteça 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 do Flutter. Primeiro, inicie os emuladores executando isto no terminal:

firebase emulators:start

Esse comando inicializa os emuladores e expõe as portas localhost com que podemos interagir com eles. 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 é possível vê-los. Primeiro, confira a interface do emulador em localhost:4000.

11563f4c7216de81.png

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

5. Emulador do Firebase Auth

O primeiro emulador que você vai usar é o do Authentication. Para começar com o emulador do Auth, clique em "Go to emulator" no card "Authentication" na IU. Você verá uma página semelhante a esta:

3c1bfded40733189.png

Essa página é semelhante à página do console da Web do Auth. Ele tem uma tabela que lista os usuários, como o console on-line, e permite que você adicione 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ê verá o processo para adicionar um usuário ao emulador do Firebase Auth e fazer o login dele usando a interface do Flutter.

Adicionar um usuário

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

  • Nome de exibição: Dash
  • E-mail: dash@email.com
  • Senha: hífen

Envie o formulário. Você verá 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 (link em inglês)

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 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 isso.

app_state.dart (link em inglês)

Duas partes do código em AppState precisam ser atualizadas. Primeiro, forneça 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 conforme 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 do tipo para o usuário agora é User?. Essa classe User vem do Firebase Auth e fornece as informações necessárias, como User.displayName, que serão discutidas mais adiante.

Esse é 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 ao FirebaseAuth para fazer login, o que retorna um objeto Future<UserCredential>. Quando o futuro estiver 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 ele fez login e a propriedade AppState.user pode ser definida. Se não houver, significa que houve um erro, e ele será impresso.

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

TODO: ícone de ação – Recarregue seu app e pressione o botão Login quando ele for renderizado. Isso faz com que o app navegue até uma página que diz "Welcome Back, Person!" na parte de cima. A autenticação precisa estar funcionando porque permite navegar até esta página, mas é preciso fazer uma pequena atualização no logged_in_view.dart para exibir o nome real do usuário.

logged_in_view.dart (link em inglês)

Altere 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 configurado no emulador quando você definiu seu primeiro usuário. Agora, o app vai mostrar a mensagem "Welcome 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 "Go to emulator" no card do Firestore. Ele será parecido com o seguinte:

Emulador:

791fce7dc137910a.png

Console do Firebase:

e0dde9aea34af050.png

Se você tiver alguma experiência com o Firestore, a página é parecida com a página do Firestore no Console do Firebase. No entanto, existem algumas diferenças notáveis.

  1. Você pode limpar todos os dados com o toque de um botão. Isso seria perigoso com dados de produção, mas é útil para uma iteração rápida. Se você estiver trabalhando em um novo projeto e seu modelo de dados mudar, é fácil fazer a limpeza.
  2. Há uma guia "Solicitações". Essa guia permite que você observe as solicitações recebidas feitas no emulador. Discutiremos essa guia com mais detalhes posteriormente.
  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.

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

gravar no Firestore

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

Este é o fluxo geral para enviar uma Entry:

  1. O usuário preenche 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 para a etapa 3 será adicionado à classe AppState. Faça a seguinte mudança em AppState.writeEntryToFirebase.

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

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

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

Com esse código adicionado, faça uma recarga automática 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 neste codelab. Ela não tem uma validação forte nem se preocupa com objetos DateTime de forma alguma.

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

Guia "Solicitações" no emulador do Firestore

Na interface, navegue até o emulador do Firestore e observe a guia "Dados". Agora há uma coleção na raiz do banco de dados chamada "Entradas". Esse formulário precisa conter as mesmas informações que você inseriu.

a978fb34fb8a83da.png

Isso confirma que o AppState.writeEntryToFirestore funcionou. Agora é possível analisar melhor a solicitação na guia "Requests". 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 para 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 app. Essa visualização mostra exatamente em qual linha das suas regras de segurança essa solicitação 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 fornece 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 dispositivos conectados. No código do Flutter, você pode ouvir (ou se inscrever) em coleções e documentos do Firestore, e seu código será notificado sempre que os dados mudarem. Nesse app, a detecção de atualizações do Firestore é feita no método chamado AppState._listenForEntries.

Esse código funciona em conjunto com os elementos 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 que fique igual 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 detecta a coleção "Entradas" 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 em 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 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. Ele 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 as importações e exportações, você pode continuar o desenvolvimento com os mesmos dados ao fazer uma pausa e retomar o desenvolvimento. Você também pode confirmar arquivos de dados no git, e outros desenvolvedores com quem trabalhar terão os mesmos dados.

Exportar dados do emulador

Primeiro, exporte os dados do emulador que você já tem. Com os emuladores 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 esse diretório.

Ao executar este comando, você verá esta saída no terminal em que o executou:

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 sendo executados, 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, 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 IU do emulador em localhost:4000. Você verá os mesmos dados com os quais estava trabalhando anteriormente.

Exportar dados automaticamente ao fechar emuladores

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

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

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

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

Também é possível usar qualquer combinação dessas opções. Esta é a nota do documento: 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 padrão, por exemplo: firebase emulators:start --import=./data-path --export-on-exit. Por fim, se quiser, transmita diferentes caminhos de diretório para as sinalizações --import e --export-on-exit.

8. Parabéns!

Você concluiu a etapa "Começar a usar o emulador do Firebase" e o Flutter. O código completo deste codelab está disponível no diretório "completo" do GitHub: Flutter Codelabs (link em inglês).

O que aprendemos

  • Como configurar um app do 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