Como gerenciar estados com Provider no Flutter: guia completo sobre

Ricarth Lima
Ricarth Lima

Compartilhe

Avalie este artigo

Se você já ouviu falar em como gerenciar estados no Flutter e está pesquisando sobre o que é provider ou como funciona o provider flutter, este artigo é para você. Vamos ensinar, do zero, como funciona o provider no Flutter e como usá-lo de forma prática para organizar seus projetos. 

Ao desenvolver projetos em Flutter, pode ter notado que a transmissão de informações e estados pode ser tornar caótica quando o projeto escala, e é visando amenizar esse problema que vamos aprender o conceito de Gerenciamento de Estados usando o Provider

Esse artigo esta organizado nos seguintes passos: 

  • O que é um gerenciador de estados; 
  • Como instalar e configurar o Provider flutter no seu projeto; 
  • Primeiras configurações do provider flutter na prática; 
  • Como consumir informações do Provider Flutter usando o Consumer; 
  • Como atualizar o estado no provider flutter; 
  • Por que usar provider flutter para gerenciar estados?; 
  • Para saber mais. 

Aprenda a utilizar essa ferramenta poderosa em diferentes projetos.  

Vamos começar? 

O que é um gerenciador de estados? 

Imagine a seguinte situação: Durante o uso de um aplicativo Flutter, imagine que uma informação (por exemplo, o título) de um objeto mudou. 

Agora seu objeto tem um novo título, porém existem vários componentes que mostram essa informação. Com o Flutter padrão, seria necessário repassar esse objeto atualizado para todos os componentes, seguindo toda a árvore de widgets filhos e netos. 

Esse modo de trabalhar com estados atende bem projetos pequenos. No entanto, à medida que o projeto cresce e uma mesma informação é utilizada em diferentes partes, organizar esse estado se torna mais complexo e difícil de manter. 

É aí que entra o Gerenciador de Estados e o conceito de “Fonte Única da Verdade” (Single Source of Truth). 

Na imagem, há um comparativo do fluxo da atualização de estados sem e com o Provider. Na esquerda, sem o provider, percebemos que a informação é mandada de pai para filho entre os componentes, de cima para baixo, na seguinte ordem: Container, Componente Filho e Componente Neto. Na direita, percebemos que ela vem diretamente de um lugar chamado “Store”, ou seja, a informação é enviada pelo Provider, de uma vez só, para o Container, Componente Filho e Componente Neto. 

Um gerenciador de estados vai ser o responsável por observar um certo objeto e avisar para todos os componentes interessados se esse objeto mudou, para que eles se atualizem. 

O Flutter tem um gerenciador de estados muito usado, simples e confiável, chamado “Provider”, e é ele que vamos aprender a usar neste artigo. 

Provider é uma biblioteca oficial e recomendada pela equipe Flutter para lidar com estados em aplicativos, sendo baseada em conceitos do Dart e muito popular para projetos profissionais. Por isso você encontra frequentemente buscas como "provider flutter" e "dart provider". 

Banner promocional da Alura destacando oferta especial com 40% de desconto em cursos de tecnologia. A mensagem convida a transformar a carreira na maior escola tech da América Latina, com botão “Aproveite” para acessar a promoção.

Como instalar  e configurar o Provider flutter no seu projeto 

Como a maior parte das bibliotecas do Flutter, o primeiro passo é acessar o site pub.dev, o onde estão as dependências de Dart e Flutter. No campo de busca que aparece, escreva “provider” e pesquise. 

Na imagem, há um print do link do provider na lista de pesquisa do pub.dev. 

Clique na dependência chamada Provider (identificada pelo selo "Flutter Favorite") e, em sua página, acesse a seção "Installing". Na data de publicação desse artigo, temos: 

Na imagem, há um print da informação dada na aba “Installing” sobre a linha que deve ser adicionada no pubspec.yaml para instalação do provider em um projeto Flutter. É possível ler a seguinte frase: “This will add a line like this to your package’s pubspec.yaml (and run an implicit ‘flutter pub get’), ou seja, “Isto vai adicionar uma linha como essa em seu pacote pubspec.yaml (e executar um implícito ´flutter pub get´). Abaixo, há as linhas “dependencies: provider: ^6.0.0. 

Por fim, adicione essa linha no nosso arquivo pubspec.yaml e rode, no terminal, o comando flutter pub get

Pronto, o Provider está pronto para uso! 

Primeiras configurações do Provider flutter na prática 

Para começar a utilizar o Gerenciador de Estados, vamos mostrar um exemplo prático, com um micro projeto de Lista de Tarefas ainda em estágio inicial. Por enquanto, existem apenas os três arquivos de código abaixo: 

lib/main.dart 

import 'package:flutter/material.dart'; 
import 'models/task.dart'; 
import 'widgets/task_widget.dart'; 
void main() { 
  runApp(MyApp()); 
} 
class MyApp extends StatelessWidget { 
  @override 
  Widget build(BuildContext context) { 
return MaterialApp( 
      debugShowCheckedModeBanner: false, 
   home: Scaffold( 
        appBar: AppBar(title: const Text("My to-do list")), 
     drawer: const Drawer(), 
     body: Center( 
       child: TaskWidget(Task("Study Flutter")), 
     ), 
   ), 
    ); 
  }
} 

Esse é o arquivo principal, responsável pela configuração inicial do MaterialApp e pela criação de uma tela que contém apenas um TaskWidget centralizado." 

lib/widgets/task_widget.dart 

import 'package:flutter/material.dart'; 
import 'package:flutter_provider/models/task.dart'; 
class TaskWidget extends StatelessWidget { 
  final Task task; 
  const TaskWidget(this.task); 
  @override 
  Widget build(BuildContext context) { 
return Card(child: Text(task.title)); 
  } 
}

Esse é o nosso TaskWidget, um widget responsável por mostrar as informações de um objeto da classe Task de forma agradável na tela. 

lib/models/task.dart 

class Task{ 
  String title; 
  Task(this.title); 
}

Por fim, a classe Task é o modelo usado para criar objetos que armazenam as informações das atividades. 

Com esses arquivos prontos, o próximo passo é configurar o Provider, indicando quem irá utilizá-lo e quais estados serão gerenciados. Para isso, é preciso alterar a linha do 'runApp', conforme mostrado abaixo: 

lib/main.dart 

void main() { 
  runApp( 
    ChangeNotifierProvider( 
   create: (context) => Task(""), 
   child: MyApp(), 
), 
  ); 
}

O ChangeNotifierProvider é responsável por notificar os widgets sempre que houver mudanças nas informações, indicando que precisam ser atualizados. 

O argumento 'create' define qual instância será gerenciada, neste caso, uma instância de Task. O 'child' representa a árvore de widgets que será notificada sobre alterações nesse estado, que neste exemplo é toda a aplicação. 

Após essa alteração, ocorrerá um erro de compilação, porque a classe 'Task' ainda não estende 'ChangeNotifier', o que é essencial para o funcionamento do Provider. 

lib/models/task.dart 

import 'package:flutter/material.dart'; 
class Task extends ChangeNotifier { 
  String title; 
  Task(this.title); 
}

Porém, até este momento, nada mudou visualmente, pois a tela ainda mostra 'Study Flutter'. Isso ocorre porque ainda estamos transferindo a instância da Task de forma tradicional, sem utilizar efetivamente o Provider. 

Na imagem, há um print da saída visual do projeto Flutter, notamos que há apenas um “Study Flutter” estático escrito na tela. 

Com essa etapa concluída, o próximo passo é receber a informação do Provider por meio do Consumer. 

Como consumir informações do Provider Flutter usando o Consumer  

O Consumer, como o nome indica, consome a informação disponibilizada pelo Provider. 

Para começar, vamos editar o arquivo task_widget para usar o “Consumer”. Vamos ao código: 

lib/widgets/task_widget.dart 

import 'package:flutter/material.dart'; 
import 'package:flutter_provider/models/task.dart'; 
import 'package:provider/provider.dart'; 
class TaskWidget extends StatelessWidget { 
  //final Task task; 
  //const TaskWidget(this.task); 
  @override 
  Widget build(BuildContext context) { 
return Consumer<Task>( 
   builder: (context, storedValue, child) { 
     return Card(child: Text(storedValue.title)); 
   }, 
    ); 
  } 
}

Nosso Widget, ao invés de retornar diretamente nosso “Card”, agora vai retornar um `Consumer<Task>`, sendo esse “Task” o tipo do objeto que queremos consumir.

Ele receberá um builder que será uma função com um context que é o contexto atual, um storedValue que é justamente a informação que ele vai receber do provider, e um child

O retorno desse builder é justamente o que queremos mostrar na tela. Note que não usamos mais task.title, que seria para pegar o título da tarefa que recebemos por parâmetro na classe TaskWidget.

Na verdade esse parâmetro e o próprio construtor nem são mais úteis, e por isso estão comentados. Agora, pegamos essa informação diretamente do storedValue.title

Agora que removemos o construtor, haverá um erro no arquivo main.dart, pois lá ainda estávamos passando aquela Task(“Study Flutter”). Logo, podemos remover isso e pronto! Nosso TaskWidget já está consumindo a informação que está no nosso provider! 

Como atualizar o estado no provider flutter 

Em situações reais, normalmente o próximo passo envolvia integrar com um banco de dados para adicionar e remover tarefas. Para fins didáticos, porém, vamos simular uma mudança criando o método abaixo dentro da classe Task: 

lib/models/task.dart 

void randomize() { 
List<String> listTasks = [ 
   "Study Flutter", 
   "Code Project", 
   "Take a break", 
   "Drink Coffee" 
    ]; 
    this.title = listTasks[Random().nextInt(listTasks.length)]; 
    notifyListeners(); 
  }

É importante observar a linha notifyListeners(), pois é ela que notifica todos os widgets ouvintes do Provider sobre a mudança. Sem essa linha, o valor é alterado, mas nada muda visualmente na aplicação. 

Com essa simples função, podemos aleatorizar uma tarefa dentre as da lista, o que é excelente para testarmos nossa funcionalidade com o Provider. Para testar, vamos acionar essa função por meio de um botão. Vamos utilizar um FloatingActionButton, que será adicionado ao Scaffold: 

lib/main.dart 

floatingActionButton: Consumer<Task>( 
       builder: (context, storedValue, child) { 
         return FloatingActionButton( 
             child: Icon(Icons.change_circle_outlined), 
                onPressed: () { 
                  storedValue.randomize(); 
                  print(storedValue.title); 
             }); 
       }, 
     ),

Da mesma forma que usamos o Consumer para ler o valor armazenado, também usamos o Consumer para pegar o valor armazenado e alterá-lo. Então, adicionamos o FloatingActionButton como retorno do builder e, quando ele for pressionado, o valor será aleatorizado. 

Ao clicar no FloatingActionButton, novas tarefas aparecerão na tela. 

Na imagem, há um print da saída visual (tela) do projeto Flutter. Notamos, agora, que a informação escrita mudou para “Drink Coffee”. 

E pronto! Agora que terminamos essa configuração, o Provider está preparado para notificar todos os widgets quando houverem alterações no nosso Task. E quais foram os benefícios de todo esse processo? 

  1. A partir de agora, a informação é entregue diretamente ao widget que utiliza esse dado, sem a necessidade de propagar pelos níveis da árvore de widgets, o que facilita a leitura e manutenção do código. 
  2. Você fez uma aplicação com alteração dinâmica sem precisar usar sequer um StatefulWidget, o que faz com que seus componentes apenas sejam recriados quando houver necessidade, portanto, tornando a aplicação muito mais eficiente! 

Por que usar provider flutter para gerenciar estados? 

O gerencimento de estados é uma técnica de Clean Code essencial para a saúde e escalabilidade de projetos Flutter grandes e complexos, pois o Provider é uma dependência que nos ajuda desenvolver esse gerenciamento com um baixo esforço. Neste artigo, oram abordados os seguintes tópicos: 

  • O que é um Gerenciador de Estados; 
  • Como instalar o Provider em um projeto Flutter; 
  • Como fazer as primeiras configurações do Provider; 
  • Como acessar uma informação armazenada no Provider; 
  • Como alterar uma informação armazenada no Provider. 

Como aprender mais sobre o tema

Espero que a leitura tenha sido útil e motivadora para experimentar a implementação dessa ferramenta. 

Mas existe muito mais conteúdo sobre Flutter Provider! Assista o curso “Flutter: Gerenciamento de Estados com Provider” da Formação Flutter da Alura

Além disso, recomendo as seguintes leituras complementares: 

Bons estudos e nós nos vemos novamente no maravilhoso mundo do Flutter! 

Avalie este artigo

Ricarth Lima
Ricarth Lima

Acredito que educação e computação podem mudar o mundo para melhor, em especial, juntas. Amo Flutter e Unity!

Veja outros artigos sobre Mobile