<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Felipe Ribeiro</title>
    <description>The latest articles on DEV Community by Felipe Ribeiro (@feliperfdev).</description>
    <link>https://dev.to/feliperfdev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F466993%2Ff3e75e5f-527c-4641-98c7-6b4dc392e269.png</url>
      <title>DEV Community: Felipe Ribeiro</title>
      <link>https://dev.to/feliperfdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/feliperfdev"/>
    <language>en</language>
    <item>
      <title>[BUILD IN PUBLIC #1] — Estou construindo um SaaS para ajudar pequenos e médios empreendedores com seus feedbacks</title>
      <dc:creator>Felipe Ribeiro</dc:creator>
      <pubDate>Tue, 20 May 2025 16:41:00 +0000</pubDate>
      <link>https://dev.to/feliperfdev/build-in-public-1-estou-construindo-um-saas-para-ajudar-pequenos-e-medios-empreendedores-com-2l0g</link>
      <guid>https://dev.to/feliperfdev/build-in-public-1-estou-construindo-um-saas-para-ajudar-pequenos-e-medios-empreendedores-com-2l0g</guid>
      <description>&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;Opa! Me chamo Felipe, tenho 23 anos e neste ano de 2025 eu decidi me juntar ao movimento de Indie Hacking. Não foi uma decisão 'do nada', já vinha tendo matérias focadas em empreendedorismo há 2 anos na faculdade (faço Engenharia de Computação desde 2021), mas somente após conhecer uma onda de pessoas trabalhando em seus próprios projetos, construindo seus sonhos e ganhando dinheiro com isso, decidi que entraria de vez para esse caminho!&lt;/p&gt;

&lt;h1&gt;
  
  
  O Projeto
&lt;/h1&gt;

&lt;p&gt;O projeto se chamará Feedlyze e estou construindo ele há pouco mais de uma semana. O projeto em si consiste em que este pequeno/médio empreendedor que possua um negócio digital extraia através da ferramenta base desse negócio (Shopify, Mercado Pago, IFood, Hotmart, canal no YT, Instagram...) o arquivo referente aos feedbacks do seu cliente — isso é uma opção comumente fornecida por essas plataformas (geralmente em CSV ou JSON) — podendo ser feedbacks simples de comentários como também feedbacks mais específicos como &lt;strong&gt;NPS (Net Promoter Score)&lt;/strong&gt; e &lt;strong&gt;CSAT (Customer Satisfaction Score)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Em posse desse arquivo, o usuário subiria ele para o Feedlyze que, com a IA, geraria um relatório detalhado com gráficos e sugestões de melhorias para seu negócio utilizando como base esses feedbacks recebidos, a fim de proporcionar insights para que este empreendedor possa crescer ainda mais seu negócio, entregando com melhor qualidade o seu serviço.&lt;/p&gt;

&lt;p&gt;Atualmente, a página do projeto está assim:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flhafogx2yjkno3zuxxrr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flhafogx2yjkno3zuxxrr.png" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Buscando o diferencial
&lt;/h2&gt;

&lt;p&gt;Se o foco são pequenos e médios empreendedores, os quais geralmente terão um caixa apertado, para eles não compensa pagar R$100, R$200, R$500 por mês em análises complexas de relatórios como muitos serviços oferecem (SurveyMonkey, Typeform, UserVoice, UserTesting...).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A precificação iniciaria em torno de R$5,00 - R$15/20 — NÃO RECORRENTE&lt;/li&gt;
&lt;li&gt;Praticidade: Sem necessidade de cadastro&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;Frontend → Flutter Web&lt;br&gt;
Backend → Supabase&lt;br&gt;
SMTP → Mailtrap&lt;br&gt;
AI → Deepseek API&lt;/p&gt;

&lt;h1&gt;
  
  
  Finalizando
&lt;/h1&gt;

&lt;p&gt;Para ser sincero, esse é meu primeiro SaaS. Creio que nesse caminho já cometi erros de principiante e ainda cometerei mais. Mas o aprendizado aqui é constante e estou disposto a aprender com meus erros.&lt;/p&gt;

&lt;p&gt;Aceito sugestões e críticas construtivas, pois é ouvindo de outros devs, empreendedores e usuários comuns que vou poder melhorar em diversos pontos dessa minha jornada.&lt;/p&gt;

&lt;h1&gt;
  
  
  Me acompanhe
&lt;/h1&gt;

&lt;p&gt;Vou estar documentando todo o processo dessa minha nova jornada no empreendedorismo lá no &lt;a href="https://x.com/feliper_dev" rel="noopener noreferrer"&gt;X/Twitter&lt;/a&gt; e talvez eu crie um canal no Youtube pra poder trazer ainda mais conteúdos de build in public e criação de micro-saas.&lt;/p&gt;

</description>
      <category>saas</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>🚀 Do zero ao primeiro SaaS: 3 erros que me ensinaram mais do que qualquer acerto</title>
      <dc:creator>Felipe Ribeiro</dc:creator>
      <pubDate>Mon, 05 May 2025 19:35:11 +0000</pubDate>
      <link>https://dev.to/feliperfdev/do-zero-ao-primeiro-saas-3-erros-que-me-ensinaram-mais-do-que-qualquer-acerto-41b8</link>
      <guid>https://dev.to/feliperfdev/do-zero-ao-primeiro-saas-3-erros-que-me-ensinaram-mais-do-que-qualquer-acerto-41b8</guid>
      <description>&lt;p&gt;Em janeiro, decidi tirar minha ideia de SaaS do papel. O objetivo? &lt;strong&gt;Aprender na prática&lt;/strong&gt; como levar um produto do conceito à loja. Confesso que foi uma onda de desafios (e ainda está sendo!).  &lt;/p&gt;

&lt;p&gt;Como era meu primeiro projeto, cometi vários equívocos. Eu queria compartilhar alguns abaixo ⤵️ — e como eles estão me ajudando a evoluir:&lt;/p&gt;

&lt;p&gt;🔥 &lt;strong&gt;Planejamento impulsivo&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Fui direto da ideia para a solução, sem mapear etapas ou prazos. &lt;strong&gt;Resultado?&lt;/strong&gt; Retrabalho e ansiedade. Hoje, priorizo ferramentas de gerenciamento e cronogramas flexíveis para manter o foco sem engessar a criatividade. &lt;/p&gt;

&lt;p&gt;🔍 &lt;strong&gt;Validação superficial&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Criei o SaaS para resolver &lt;em&gt;meu&lt;/em&gt; problema, mas não validei se era uma dor real do mercado. &lt;strong&gt;Consequência?&lt;/strong&gt; Perdi tempo competindo com soluções já consolidadas. Aprendi que entrevistas com potenciais usuários são tão importantes quanto o código.&lt;/p&gt;

&lt;p&gt;💸 &lt;strong&gt;Precificação "no feeling"&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Foquei em funcionalidades incríveis, mas não pensei em como monetizá-las de forma atraente. &lt;strong&gt;Lição?&lt;/strong&gt; Agora estudo modelos de precificação &lt;em&gt;antes&lt;/em&gt; de sair desenvolvendo novas features, usando cases de sucesso como referência.&lt;/p&gt;

&lt;p&gt;✨ &lt;strong&gt;O saldo positivo?&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Esses tropeços me deram algo valioso: &lt;strong&gt;clareza&lt;/strong&gt;. Hoje entendo melhor que errar faz parte do processo — desde que cada erro vire um degrau para iterar.&lt;/p&gt;

&lt;p&gt;E você? Já passou por situações assim em seus projetos?&lt;/p&gt;

</description>
      <category>saas</category>
      <category>programming</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>O que são Data Warehouses e o sistema OLAP</title>
      <dc:creator>Felipe Ribeiro</dc:creator>
      <pubDate>Sun, 01 Sep 2024 01:41:54 +0000</pubDate>
      <link>https://dev.to/feliperfdev/o-que-sao-data-warehouses-e-o-sistema-olap-2d6k</link>
      <guid>https://dev.to/feliperfdev/o-que-sao-data-warehouses-e-o-sistema-olap-2d6k</guid>
      <description>&lt;p&gt;Data Warehouse (DW / ~Armazém de dados) é um sistema de armazenamento de dados projetado para suportar a análise de grande quantidades de dados. Ele funciona em conjunto a um sistema &lt;strong&gt;OLAP&lt;/strong&gt; (Processamento Analítico Online), que é uma tecnologia usada para organizar grandes bancos de dados e analisá-los sob &lt;strong&gt;múltiplas perspectivas&lt;/strong&gt;. Nele podemos centralizar dados de diversas fontes em um só repositório, sejam dados provenientes de uma &lt;strong&gt;planilha excel, um PDF, uma API Rest, um JSON, um banco de dados&lt;/strong&gt;, basicamente do tipo de fonte que você quiser. Ele processa essas informações usando várias ferramentas para que os dados estejam prontos para finalidades analíticas.&lt;/p&gt;

&lt;p&gt;A ideia de um DW é poder integrar dados que, inicialmente, estão distribuídos em sistemas isolados e centralizar essas informações para que se tenha uma visão unificada e consistente desses dados, facilitando a análise e geração de relatórios detalhados. É muito utilizado por empresas que buscam alavancar vendas de produtos, descobrir concorrências/tendências de mercado, identificar pontos de melhoria dentro do próprio negócio e por aí vai.&lt;/p&gt;

&lt;h3&gt;
  
  
  E como funciona um OLAP?
&lt;/h3&gt;

&lt;p&gt;Basicamente, podemos dividir em uma arquitetura com 3 camadas: 1. coleta dos dados; 2. extração, transformação e carregamentos dos dados; 3. Apresentação dos dados. Ou seja, primeiro os dados são coletados de diversas fontes, depois passam pelo processo ETL (Extraction, Transforming &amp;amp; Loading), onde esses dados são calculados, tratados e armazenados em um "cubo OLAP", por fim estes dados são disponibilizados para serem feitas consultas e geração de gráficos, relatórios e o que mais for necessário para facilitar sua análise.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggxgy6tyhpc00t76yvwj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggxgy6tyhpc00t76yvwj.png" alt="Processo de uma arquitetura OLAP" width="640" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.techtarget.com/searchdatamanagement/definition/OLAP" rel="noopener noreferrer"&gt;Fonte&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  O que seria esse "cubo OLAP"?
&lt;/h3&gt;

&lt;p&gt;Digamos que eu quero analisar as vendas de um produto em determinadas regiões do Brasil e em um determinado período (exemplo: durante cada quadrimestre). Logo, teremos uma análise em múltiplas dimensões: produto, local e tempo, podendo executar queries por essas dimensões para encontrar e filtrar dados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo0x7h9i0fjjgbivf3g1s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo0x7h9i0fjjgbivf3g1s.png" alt="Representação exemplificada de um cubo OLAP" width="500" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.collidu.com/presentation-olap-cube" rel="noopener noreferrer"&gt;Fonte&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em teoria, um cubo OLAP pode conter um número infinito de camadas, e cubos menores podem existir dentro dessas camadas — por exemplo, cada camada de loja pode conter cubos organizando vendas por vendedor ou produto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operações OLAP
&lt;/h3&gt;

&lt;p&gt;A partir do cubo OLAP, podemos realizar operações para analisar os dados:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sumarização&lt;/strong&gt;: resume os dados para atributos específicos. Por exemplo, em uma visualização de vendas de produtos de acordo com sua localização — Nova York, Califórnia, Londres e Tóquio — pode ser resumida para uma exibição dos dados de vendas com base nos países EUA, Reino Unido e Japão. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detalhamento&lt;/strong&gt;: é o oposto da operação de sumarização. Por exemplo, passar da visualização de dados de vendas por ano para uma visualização de vendas por mês.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decomposição&lt;/strong&gt;: cria uma exibição bidimensional do cubo OLAP. Ao decompor o cubo, podemos criar uma tabela que contém as vendas de produtos em determinadas cidades num mês específico. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fragmentação&lt;/strong&gt;: cria um "subcubo" menor a partir de um cubo OLAP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pivotagem&lt;/strong&gt;: envolve a rotação do cubo OLAP ao longo de uma de suas dimensões para obter uma perspectiva diferente sobre o modelo de dados multidimensional. Por exemplo, um cubo OLAP tridimensional tem as seguintes dimensões nos respectivos eixos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eixo X: produto &lt;/li&gt;
&lt;li&gt;Eixo Y: localização&lt;/li&gt;
&lt;li&gt;Eixo Z: tempo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com a pivotagem, o cubo OLAP pode ter a seguinte configuração:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eixo X: localização&lt;/li&gt;
&lt;li&gt;Eixo Y: tempo&lt;/li&gt;
&lt;li&gt;Eixo Z: produto&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Fontes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/pt/what-is/olap/" rel="noopener noreferrer"&gt;https://aws.amazon.com/pt/what-is/olap/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.ibm.com/br-pt/topics/olap" rel="noopener noreferrer"&gt;https://www.ibm.com/br-pt/topics/olap&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.sprinkledata.com/blogs/olap" rel="noopener noreferrer"&gt;https://www.sprinkledata.com/blogs/olap&lt;/a&gt;&lt;br&gt;
&lt;a href="https://computerisation.co.uk/blog/what-is-a-data-warehouse" rel="noopener noreferrer"&gt;https://computerisation.co.uk/blog/what-is-a-data-warehouse&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>olap</category>
      <category>sql</category>
    </item>
    <item>
      <title>How to create your own element filter in Dart Language</title>
      <dc:creator>Felipe Ribeiro</dc:creator>
      <pubDate>Sun, 24 Mar 2024 00:36:49 +0000</pubDate>
      <link>https://dev.to/feliperfdev/how-to-create-your-own-element-filter-in-dart-language-107a</link>
      <guid>https://dev.to/feliperfdev/how-to-create-your-own-element-filter-in-dart-language-107a</guid>
      <description>&lt;p&gt;Couple of weeks ago I was submitted for a task that demmands a way to standardize an element filter (from DIFFERENT kinds of elements). Therefore, instead of install a new dependency, I decided to create a simple algorithm that receives a generic element list and determines from which field this element should be filtered by.&lt;/p&gt;

&lt;p&gt;Without further delay, let's analyse what I did:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;filterElementsByField&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
  &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fieldToCompare&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;texts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fieldToCompare&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


  &lt;span class="c1"&gt;// If nothing was typed or if is just empty, it'll return the full list content.&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;texts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="c1"&gt;// This is the text that is contained in the field which was parsed to the function&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;fieldText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fieldToCompare&lt;/span&gt;
          &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;queryText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fieldText&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queryText&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;// It'll try to retrieve all the content that matches with the text it contains at the parsed field. It doesn't matter if the word has blank spaces between of them.&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fieldText&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queryText&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, let's try to apply this on a little sample code. Initially, I'll create a sample class (Pokemon) and a sample list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pokemon&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,}&lt;/span&gt;
   &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pokemonList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="nl"&gt;number:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s"&gt;"Pikachu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="nl"&gt;number:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s"&gt;"Galarian Moltres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="nl"&gt;number:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s"&gt;"Moltres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="nl"&gt;number:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s"&gt;"Charizard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="nl"&gt;number:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s"&gt;"Charizard X"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="nl"&gt;number:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s"&gt;"Charizard Y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the filtered list, we'll pass our initial list, then the class field we want to be filtered and, finally, the query we want to match with the elements from the list by attending the function algorithm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;filteredList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filterElementsByField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="n"&gt;pokemonList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkmn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pkmn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;"mo"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To print all the results, we'll do it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filteredList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This filtered list will retrieve for us the following result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;['Moltres', 'Galarian Moltres']

// They match with query "mo"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's try a new one sample:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;filteredList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filterElementsByField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="n"&gt;pokemonList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkmn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pkmn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;"ch"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, this new filtered list will retrieve for us the following result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;['Charizard', 'Charizard X', 'Charizard Y']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It'd be different if we just tried to do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;filteredList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filterElementsByField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="n"&gt;pokemonList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkmn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pkmn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;"x"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;['Charizard X']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seeing all the results, it's clear that it doesn't matter if the query matches with the first, second or another word from the same object field (as we saw like "mo" matching with "Moltres" from "Galarian Moltres" and "Moltres") and doesn't matter the word case (if it's lower, upper, alterning, capitalized...).&lt;/p&gt;

&lt;p&gt;I highly appreciate if you read this far. If this helped you with anything, so I'm happy.&lt;/p&gt;

</description>
      <category>dart</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>flutter</category>
    </item>
    <item>
      <title>Using Github Actions to publish your Flutter APP to Firebase App Distribution</title>
      <dc:creator>Felipe Ribeiro</dc:creator>
      <pubDate>Thu, 05 Jan 2023 04:04:15 +0000</pubDate>
      <link>https://dev.to/feliperfdev/using-github-actions-to-publish-your-flutter-app-to-firebase-app-distribution-1dcf</link>
      <guid>https://dev.to/feliperfdev/using-github-actions-to-publish-your-flutter-app-to-firebase-app-distribution-1dcf</guid>
      <description>&lt;h2&gt;
  
  
  Hey, everyone! 👋🏻
&lt;/h2&gt;

&lt;p&gt;I want to start talking about my decision for this year, which is to start to write more tech articles to help people, increase my knowledges (cuz I need to study either ^^) and also improve my english writting skills. So, this will be the beggining of this journey and I hope you all could enjoy it :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/feliperfdev/using-github-actions-to-publish-your-flutter-app-to-firebase-app-distribution-1dcf#s1"&gt;1. Why am I writting this article?&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/feliperfdev/using-github-actions-to-publish-your-flutter-app-to-firebase-app-distribution-1dcf#s2"&gt;2. Firebase App Distribution&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/feliperfdev/using-github-actions-to-publish-your-flutter-app-to-firebase-app-distribution-1dcf#s3"&gt;3. The manually way&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/feliperfdev/using-github-actions-to-publish-your-flutter-app-to-firebase-app-distribution-1dcf#s4"&gt;4. The GitHub workflows way&lt;/a&gt; (main topic)&lt;br&gt;
&lt;a href="https://dev.to/feliperfdev/using-github-actions-to-publish-your-flutter-app-to-firebase-app-distribution-1dcf#s5"&gt;5. Final workflow yaml file result&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/feliperfdev/using-github-actions-to-publish-your-flutter-app-to-firebase-app-distribution-1dcf#s6"&gt;6. Testing it!&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Why am I writting this article? &lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Few months ago I started to develop a Flutter app side-project, which is not available yet, but I intend to publish it on app stores when I feel that it is ready for MVP release.&lt;br&gt;
On this project, I'm using Firebase database to store the app data, authentication, files storaging and some other features. BUT we have one that is the main topic of this article: &lt;strong&gt;Firebase App Distribution&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Firebase App Distribution &lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Firebase has it own functionality whose job is literally distribute your app to an user (or a group of users).&lt;br&gt;
When we're talking about Flutter apps, we're also talking about downloading this apps at our mobile devices (in case mobile apps, I'm not going to talk about Flutter Web at this article). Maybe you or your team wanna test it or show it for the team manager or team leader, whatever.&lt;br&gt;
This is the "nice" but rough way to do it. Uploading your app file to Firebase App Distribution.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. The &lt;strong&gt;manually&lt;/strong&gt; way &lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;First of all, of course, you'll need to generate a build of your Flutter app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter build apk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter build aab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you get into your Firebase project console, you have in the left side a shortcuts list, and you will probably see an option named 'App Distribution'. Click on it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fma6dqeb0owmy62ek02c8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fma6dqeb0owmy62ek02c8.png" alt="Shortcuts" width="235" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll see a big dashed blue box asking you to upload your app APK or AAB file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdawoa712yid86sitpcrt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdawoa712yid86sitpcrt.png" alt="Dashed blue box" width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, it will appear a card with a text field to put the tester e-mail or the name of a tester group (which you can create by clicking at third top navigation bar).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ylwdxi1ziv1yk5pkxzb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ylwdxi1ziv1yk5pkxzb.png" alt="Send to testers" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, you'll just need to press 'Next' and 'Send to testers'.&lt;/p&gt;

&lt;p&gt;Well done! Now, your app is on the devices of all the testers you sent it.&lt;br&gt;
But... Doing this EVERY time sounds like a waste of time. Isn't? Maybe. Maybe not.&lt;/p&gt;

&lt;p&gt;But we can do it better. Follow me to the next topic!&lt;/p&gt;
&lt;h2&gt;
  
  
  4. The &lt;strong&gt;GitHub Actions&lt;/strong&gt; way &lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Now, in the main topic of this article, I'll show you how automate this process of uploading your app to Firebase App Distribution and send it to testers.&lt;br&gt;
In the end of this topic, you'll know how to do this process just by pushing or opening a pull request on a specific Git branch of your project.&lt;/p&gt;

&lt;p&gt;In your project, create a path named &lt;code&gt;.github/workflows&lt;/code&gt;, just like that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52wznmlwrunibcjg95d1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52wznmlwrunibcjg95d1.png" alt="Folders path" width="279" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inside of it, create a &lt;code&gt;.yaml&lt;/code&gt; file with the name of your workflow. I named mine as 'firebase_workflow.yaml'.&lt;/p&gt;

&lt;p&gt;Let's beggin by giving a name to the workflow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Firebase APP Workflow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we will need to determine when this workflow will be triggered. Pushing to a branch? Creating a pull request to a branch?&lt;/p&gt;

&lt;p&gt;Exemple of how it should looks like the yaml file until here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Firebase APP workflow&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to put jobs on our workflow file. Above we have an exemple of setting that is very important for the whole workflow operation.&lt;/p&gt;

&lt;p&gt;I created a key named &lt;code&gt;firebase_distribution&lt;/code&gt; and gave it the name "Firebase App Distribution". Then, I setted the virtual machine which would it runs on. &lt;a href="https://github.com/actions/runner-images" rel="noopener noreferrer"&gt;You can read more about this here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;firebase_distribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Firebase App Distribution&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt; &lt;span class="c1"&gt;## virtual machine&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;12.x"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we have two important initial steps to define. The &lt;a href="https://github.com/actions/checkout" rel="noopener noreferrer"&gt;first one&lt;/a&gt; is an official GitHub Action used to check-out a repository so a workflow can access it. The &lt;a href="https://github.com/actions/setup-java" rel="noopener noreferrer"&gt;second one&lt;/a&gt; it's pretty more complex but, briefly, downloads and set up a requested version of Java.&lt;/p&gt;

&lt;p&gt;Continuing the steps:&lt;/p&gt;

&lt;p&gt;Give a name to this step, now we gonna make our workflow decode the most important file which makes Firebase work on our project: the &lt;code&gt;google-services.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Decode google-services.json&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
            &lt;span class="na"&gt;GOOGLE_SERVICES_JSON&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GOOGLE_SERVICES_JSON }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "$GOOGLE_SERVICES_JSON" &amp;gt; android/app/google-services.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;em&gt;env&lt;/em&gt; key we put another key called &lt;em&gt;GOOGLE_SERVICES_JSON&lt;/em&gt;. But, for now, I'll need to explain what is this "secrets.GOOGLE_SERVICES_JSON" here.&lt;/p&gt;

&lt;p&gt;For this, open your Github project repository and get into settings page.&lt;/p&gt;

&lt;p&gt;On the left side options, look for the security session and click on "Secrets" &amp;gt; "Actions".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfmjovwlx0u9d7urnplq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfmjovwlx0u9d7urnplq.png" alt="options" width="311" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to create 3 secret keys. Each one for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Firebase App ID&lt;/li&gt;
&lt;li&gt;Firebase Token&lt;/li&gt;
&lt;li&gt;Google Services Json&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Name them by your preference.&lt;/p&gt;

&lt;p&gt;The Firebase App ID can be found by following this short click steps on your Firebase project console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63paxi9fn335p562z7tn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63paxi9fn335p562z7tn.png" alt="Firebase App ID" width="462" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We just need to copy and paste it on our secret key.&lt;/p&gt;

&lt;p&gt;Firebase token can be obtained by running a few commands on your machine.&lt;/p&gt;

&lt;p&gt;At first, we'll need to install &lt;a href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm/" rel="noopener noreferrer"&gt;npm&lt;/a&gt; and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g firebase-tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, run this second command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;firebase login:ci
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, the token will be shown by your CLI.&lt;/p&gt;

&lt;p&gt;For the last key, we just need to open the &lt;code&gt;google-services.json&lt;/code&gt; on our project in path &lt;em&gt;"android/app/google-services.json"&lt;/em&gt;, copy the whole content inside and paste it on the respective secret key in your Github project repository.&lt;/p&gt;

&lt;p&gt;Now, we can get back into our workflow and understand what will happen from now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Decode google-services.json&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
            &lt;span class="na"&gt;GOOGLE_SERVICES_JSON&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GOOGLE_SERVICES_JSON }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "$GOOGLE_SERVICES_JSON" &amp;gt; android/app/google-services.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically, using &lt;strong&gt;&lt;em&gt;secrets.KEY_NAME&lt;/em&gt;&lt;/strong&gt; allows us to access our project secret keys.&lt;/p&gt;

&lt;p&gt;We're accessing the secret key named &lt;code&gt;GOOGLE_SERVICES_JSON&lt;/code&gt; and running a command on it.&lt;/p&gt;

&lt;p&gt;Now, we can continue writting our workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;subosito/flutter-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stable"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;subosito/flutter-actions@v1 is just a Flutter enviroment running on our workflow. So, now we have 'access' to Flutter enviroment, we can choose a Flutter channel to use. &lt;a href="https://github.com/marketplace/actions/flutter-action" rel="noopener noreferrer"&gt;Read about this action here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From now, we will run Flutter commands inside our workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter pub get&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter build apk&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-apk&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/app/outputs/apk/release/app-release.apk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that already known commands like &lt;code&gt;flutter pub get&lt;/code&gt; and &lt;code&gt;flutter build apk&lt;/code&gt; now it shows up on our workflow. But, to upload the generated app file (artifact), we'll need to use the action &lt;a href="https://github.com/actions/upload-artifact" rel="noopener noreferrer"&gt;upload-artifact@v1&lt;/a&gt; and parse the build path which it will be storing the app file.&lt;/p&gt;

&lt;p&gt;To finally finish this (I swear), we complete our workflow with a Firebase action that will have the responsability to upload the app to Firebase App Distribution. Read about &lt;a href="https://github.com/wzieba/Firebase-Distribution-Github-Action" rel="noopener noreferrer"&gt;wzieba/Firebase-Distribution-Github-Action&lt;/a&gt;. &lt;strong&gt;This action uploads your artifacts with .apk, .aab and .ipa (this last one for iOS) extensions to Firebase App Distribution.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;upload artifact to Firebase App Distribution&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wzieba/Firebase-Distribution-Github-Action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{secrets.FIREBASE_APP_ID}}&lt;/span&gt;
            &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{secrets.FIREBASE_TOKEN}}&lt;/span&gt;
            &lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;testers&lt;/span&gt;
            &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/app/outputs/flutter-apk/app.apk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll need to parse the remeaning secret keys, the tester group name (which you created at your Firebase project console) and the file path. In Flutter, by default, it is stored at &lt;code&gt;build/app/outputs/apk/release/app-release.apk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's it! Our workflow process file is done!&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Final workflow yaml file result &lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is how your workflow file should looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Firebase APP workflow&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;firebase_app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Firebase Workflow&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt; &lt;span class="c1"&gt;## virtual machine&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;12.x"&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Decode google-services.json&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
            &lt;span class="na"&gt;GOOGLE_SERVICES_JSON&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GOOGLE_SERVICES_JSON }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "$GOOGLE_SERVICES_JSON" &amp;gt; android/app/google-services.json&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;subosito/flutter-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stable"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter pub get&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter build apk&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-apk&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/app/outputs/apk/release/app-release.apk&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload to Firebase App Distribution&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wzieba/Firebase-Distribution-Github-Action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{secrets.FIREBASE_APP_ID}}&lt;/span&gt;
            &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{secrets.FIREBASE_TOKEN}}&lt;/span&gt;
            &lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;testers&lt;/span&gt;
            &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/app/outputs/flutter-apk/app.apk&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Testing it! &lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Now, we just need to push our project to github's project branch which we had chosen or merge pull request (it depends on what did you choose to do) to trigger the workflow.&lt;/p&gt;

&lt;p&gt;After that, you can see the process working by clicking at "Actions" tab in your project repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnr713hdhm42rauk68yxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnr713hdhm42rauk68yxd.png" alt="Actions tab" width="106" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how it should your workflow alert looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiuflfpfe54r0w7wqthbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiuflfpfe54r0w7wqthbp.png" alt="Workflow" width="768" height="88"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  That's it!
&lt;/h2&gt;

&lt;p&gt;Thanks A LOT for reading until here! I hope this article may help you create github actions workflows to upload your app to Firebase APP Distribution.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>webdev</category>
      <category>learning</category>
      <category>coding</category>
    </item>
    <item>
      <title>Consumindo arquivos JSON no Dart</title>
      <dc:creator>Felipe Ribeiro</dc:creator>
      <pubDate>Tue, 27 Jul 2021 15:10:11 +0000</pubDate>
      <link>https://dev.to/feliperfdev/consumindo-arquivos-json-no-dart-20cc</link>
      <guid>https://dev.to/feliperfdev/consumindo-arquivos-json-no-dart-20cc</guid>
      <description>&lt;p&gt;Neste artigo pretendo mostrar como consumir arquivos JSON no Dart. Não é bem como consumir uma API, algo que dependa de requisições web. Se trata de fato em consumir arquivos JSON da máquina local e atribuindo-os a objetos Dart.&lt;/p&gt;

&lt;h2&gt;
  
  
  Estruturando o arquivo JSON
&lt;/h2&gt;

&lt;p&gt;Vamos criar um arquivo JSON em nosso projeto e, em seguida, estruturá-lo da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"nome"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bulbassaur"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"regiao"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kanto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"tipos"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Grass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Poison"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"nome"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ivyssaur"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"regiao"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kanto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"tipos"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Grass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Poison"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"nome"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Charmander"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"regiao"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kanto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"tipos"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Fire"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Antes de mais nada, vamos pegar esse arquivo JSON que escrevemos e chamá-lo de &lt;strong&gt;poke_db.json&lt;/strong&gt;, por exemplo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Definindo a classe
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pokemon&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;regiao&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;tipos&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;regiao&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tipos&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Criando o método de deserialização do JSON
&lt;/h2&gt;




&lt;p&gt;Antes de partirmos para a criação do método, vamos entender o que é deserializar um objeto JSON?&lt;br&gt;
O que acontece é que o que está presente em nosso "poke_db.json" são dados prontos e fresquinhos para serem consumidos, e nós precisamos de alguma forma utilizar esses dados. Para isso, nós pegamos esses dados "fresquinhos" e reconstruímos eles na forma de um &lt;code&gt;model&lt;/code&gt;, um modelo. No caso, atribuímos esses dados aos atributos de uma classe.&lt;/p&gt;



&lt;p&gt;No mesmo arquivo da classe criada, criaremos o método fromJson().&lt;br&gt;
O que acontece nesse método?&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;fromJson&lt;/strong&gt; serve para atribuir valores vindos de um objeto JSON para sua classe. Um objeto JSON é reconhecido como um Map devido ao seu comportamento e estruturação de chave-valor. Então pegamos os atributos da classe e fazemos com que recebam os valores do JSON referentes às chaves do Map correspondentes a estes.&lt;br&gt;
Basicamente, esta função é uma espécie de &lt;em&gt;MAPEAMENTO&lt;/em&gt; da classe para um objeto JSON.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;nome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'nome'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;regiao&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'regiao'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;tipos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'tipos'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;[]();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Por qual motivo a tipagem do Map utilizado como parâmetro é &lt;code&gt;&amp;lt;String, dynamic&amp;gt;&lt;/code&gt;?&lt;br&gt;
Bom, já sabemos que o tipo informado no lado esquerdo é a tipagem das chaves. Já no direito, é a tipagem dos valores.&lt;br&gt;
No caso, utilizamos o dynamic para os valores justamente pelo motivo de que podemos ter números (int, double), textos (String), listas (List), Maps...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Exemplo de um JSON genérico&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"chave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"valor"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Vamos consumir o objeto JSON
&lt;/h2&gt;

&lt;p&gt;Vamos criar um arquivo chamado &lt;code&gt;poke_repository.dart&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Neste arquivo iremos criar algumas funções que ficarão responsáveis pelo processo de consumo do nosso objeto JSON.&lt;/p&gt;

&lt;p&gt;Primeiramente iremos realizar alguns &lt;code&gt;imports&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:async'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/services.dart'&lt;/span&gt; &lt;span class="kd"&gt;show&lt;/span&gt; &lt;span class="n"&gt;rootBundle&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:convert'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:pokemon_json/poke_model.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// import da classe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criaremos uma função para &lt;strong&gt;carregar&lt;/strong&gt; a String contendo todo o arquivo &lt;code&gt;poke_db.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;É muito importante lembrar de colocarmos o caminho do arquivo JSON nos assets do nosso &lt;code&gt;pubspec.yaml&lt;/code&gt;!&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;assets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;lib/poke_db.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_carregarPokemonJSON&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;rootBundle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'lib/poke_db.json'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Aqui passamos o [caminho] do arquivo JSON&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tendo a String do nosso arquivo JSON carregada, vamos criar uma função que irá nos retornar a lista contendo os objetos Dart de Pokémon.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Como temos uma lista em nosso objeto JSON, podemos então dizer para nossa função que pode aguardar uma List&amp;lt;Pokemon&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;carregarPokemon&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Atribuímos a String de todo o JSON para a variável pokeJsonString&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;pokeJsonString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_carregarPokemonJSON&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Agora utilizamos o método json.decode() para "decodificarmos" essa String&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;respostaJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pokeJsonString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// criando lista genérica para armazenar os Pokémon do objeto JSON&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;lista&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;[];&lt;/span&gt;

  &lt;span class="c1"&gt;// Atribuindo cada objeto da lista JSON para a classe Dart Pokémon utilizando o método Pokemon.fromJson()&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;respostaJson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;poke&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;lista&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poke&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// e finalmente teremos a lista com nossos Pokémon&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lista&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto, com esta última função sendo chamada em alguma parte de seu código você já pode ter acesso aos dados do &lt;code&gt;poke_db.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

 &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;listaPokemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;carregarPokemon&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

 &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listaPokemon&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Bulbassaur&lt;/span&gt;


 &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pokemon&lt;/span&gt; &lt;span class="n"&gt;pkmn&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;listaPokemon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkmn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="cm"&gt;/*
   Bulbassaur
   Ivyssaur
   Charmander
  */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Artigo que possa vir a te ajudar em caso de dúvidas mais específicas em relação ao Dart&lt;br&gt;
&lt;a href="https://github.com/pksasso/dart4noobs" rel="noopener noreferrer"&gt;Dart4Noobs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>json</category>
      <category>mobile</category>
    </item>
  </channel>
</rss>
