Com tantas opções, é fácil ficar confuso ao escolher um gerente de estado para seu aplicativo. Parece que diversas soluções de gerenciamento de estado são lançadas com mais frequência do que se pode imaginar, cada uma esperando apresentar uma maneira única e mais fácil de lidar com o estado.

Neste artigo, iremos abordar duas ferramentas de gerenciamento de estado diferentes: Provedor e Riverpod. Examinaremos rapidamente cada ferramenta para ver as melhorias que o Riverpod oferece e por que alguém pode escolhê-la ao invés do Provider, então destacaremos os problemas que o Provider tem com as soluções que a Riverpod oferece.

Este post presume que você esteja familiarizado com o Flutter. Como não é uma introdução ao Riverpod ou ao pacote de gerenciamento de estado do Provedor, não iremos nos aprofundar muito em seus recursos-apenas o suficiente para apontar as comparações. Esta postagem foca no Riverpod como um sucessor natural do Provider.

O que é um estado?

Um estado é uma informação mantida por um widget quando construído e pode mudar quando o widget se atualiza. Certos dados ou informações armazenados e transmitidos através ou dentro dos widgets em um aplicativo são chamados de”o estado”.

Tudo no Flutter trata do tratamento e manipulação de detalhes precisos, seja recuperando-os ou exibindo-os para o usuário de uma forma ou de outra. O método que você escolhe para lidar com o estado impacta diretamente o comportamento e a segurança do aplicativo.

Gerenciamento de estado

O gerenciamento de estado se refere às técnicas ou métodos usados ​​para lidar com o estado em um aplicativo. As técnicas de gestão do estado são numerosas e atendem a várias necessidades. Não existe um tamanho único para qualquer técnica de gerenciamento de estado; você escolhe aquele que atende às suas necessidades e funciona melhor para você.

Riverpod

Riverpod é um pacote de gerenciamento de estado lançado por Remi Rousselet (o criador do Provider). Rousselet obteve a palavra Riverpod reorganizando as letras da palavra”Provedor”.

O Riverpod foi construído principalmente para resolver as falhas do Provedor (discutiremos algumas dessas falhas mais tarde). É rápido e fácil de usar e vem direto da caixa como um pacote rápido e leve para gerenciamento de estado.

Desde seu lançamento oficial, Riverpod tem criado ondas em toda a comunidade de gerenciamento de estado por causa de sua simplicidade , embora muito poderoso, gerenciando o estado de uma maneira segura de compilação.

No Riverpod, você declara o provedor e o chama de onde quiser. Riverpod é fácil, simples e rápido.

Confira este exemplo de gerenciamento de estado com Riverpod. Primeiro, envolvemos nosso aplicativo inteiro dentro de um ProviderScope. ProviderScope faz o escopo de todos os provedores criados no aplicativo e torna possível usar qualquer provedor declarado globalmente:

import’package: flutter/material.dart’; import’package: flutter_riverpod/flutter_riverpod.dart’; void main ()=> runApp (ProviderScope (filho: RiverPodApp ()));

Em seguida, declare o provedor:

final favoriteProvider=ChangeNotifierProvider ((ref)=> new Favorites ());

Aqui, usamos ChangeNotifierProvider. Este provedor sempre nos fornecerá a classe Favorites.

Para usar os provedores dentro de nosso widget, estenda o ConsumerWidget:

class RiverPodApp extends ConsumerWidget {const RiverPodApp ({Key? Key}): super (tecla: tecla); @override Widget build (BuildContext context, ScopedReader watch) {return MaterialApp (home: Scaffold (appBar: AppBar (title: Text (‘Minha fruta favorita é’+ watch (favoriteProvider).fruit),), body: Center (child: Coluna (filhos: [FruitButton (‘Maçãs’), FruitButton (‘Laranjas’), FruitButton (‘Bananas’),],),),),); }}

Observe que o ConsumerWidget nos dá acesso ao ScopedReader dentro do método build, que fornece acesso ao conteúdo do provedor.

Neste exemplo, criamos três botões para frutas diferentes. Quando cada botão é clicado, o nome da fruta muda na barra de aplicativos. Quando você inicia o aplicativo, a barra do aplicativo diz: “Minha fruta favorita é desconhecida”. Quando cada botão de fruta é clicado, o nome da fruta muda.

A mudança é possível porque a barra do app observa a fruta variável criada na classe Favorita (por padrão, é chamada de”desconhecida”). Quando cada botão é clicado, a função changeFruit é chamada, atribuindo à variável fruit um novo valor e atualizando o widget:

class FruitButton extends StatelessWidget {final String fruit; FruitButton (esta.fruta); @override Widget build (BuildContext context) {return ElevatedButton (child: Text (fruit), onPressed: () {context.read (favoriteProvider).changeFruit (fruit);},); }} class Favorites extends ChangeNotifier {String fruit=’unknown’; void changeFruit (String newFruit) {fruit=newFruit; notificarListeners (); }}

Por que escolher Riverpod?

Listados abaixo estão vários motivos pelos quais alguém pode escolher Riverpod:

Riverpod é seguro em tempo de compilação Não depende diretamente do Flutter SDK Riverpod pode ser usado para criar e aplicar um fluxo de dados unidirecional com classes de modelo que são imutáveis ​​(o que significa que não mudam) Riverpod não depende diretamente da árvore de widgets; sua operação é semelhante a um localizador de serviço. Os provedores são declarados globalmente e podem ser usados ​​em qualquer lugar no aplicativo Riverpod dá acesso de widgets aos provedores por meio de ScopedReader, que é passado para o método de construção e finalmente consumido por meio da classe ConsumerWidget

Problemas com Provedor que Riverpod resolve

Existem várias falhas no Provider que o Riverpod resolve.

Primeiro, ao contrário do Riverpod, o Provider depende exclusivamente do Flutter. Como seus widgets são usados ​​para fornecer objetos ou estados na árvore, ele depende exclusivamente do Flutter, resultando em uma mistura de código de IU e injeções de dependência.

Por outro lado, Riverpod não depende de widgets; você pode declarar um provedor no Riverpod e usá-lo em qualquer lugar do aplicativo, independentemente do widget pai. Os provedores no Riverpod são declarados como variáveis ​​globais e colocados dentro de qualquer arquivo.

O provedor também depende apenas do tipo de objeto para resolver o objeto solicitado pelo widget. Se você fornecer dois do mesmo tipo, poderá obter apenas um mais perto do local da chamada. No entanto, Riverpod oferece suporte a vários provedores do mesmo tipo, que você pode usar em qualquer lugar e a qualquer hora.

Com o Provider, se você tentar acessar um tipo não fornecido, terá um erro no tempo de execução. Esse erro de tempo de execução não deve ser assim, porque devemos detectar o máximo de erros possível durante a compilação do aplicativo. Riverpod resolve isso detectando erros durante a compilação do aplicativo, tornando a experiência do usuário mais perfeita.

A combinação de dois ou mais provedores pode levar a um código terrivelmente aninhado. Riverpod lida com esse problema usando ProviderReference. As dependências dos provedores são injetadas e chamadas a qualquer momento, o que significa que um provedor pode depender de outro provedor e ser chamado facilmente por ProviderReference.

Aqui está um exemplo:

Future main () async {WidgetsFlutterBinding.ensureInitialized (); final sharedPreferences=await SharedPreferences.getInstance (); runApp (MultiProvider (fornecedores: [Provider (criar: (_)=> sharedPreferences), ChangeNotifierProxyProvider (criar: (_)=> HomeViewModel (sharedPreferences), atualizar: (contexto, sharedPreferences, _)=> HomeViewModel (sharedPreferences),),], filho: Consumer (builder: (_, viewModel)=> HomeView (viewModel),),)); }

Neste exemplo, temos HomeView, que recebe um argumento HomeViewModel. Mas como HomeViewModel depende de SharedPreferences, precisamos dos widgets MultiProvider e ProxyProvider para colocar tudo junto.

Com isso em mente, podemos ver que há muito código clichê. Seria melhor se todos esses provedores estivessem fora do widget em vez de dentro da árvore de widgets.

Em comparação, aqui está um exemplo de um provedor dependendo de outro provedor em Riverpod sem nenhum dos problemas de aninhamento que o provedor apresenta:

final appTokenProvider=StateProvider ((_)=>”); final authenticateFBUser=FutureProvider ((ref) async {final authFBResult=await ref.read (authProvider).login (); ref.read (appTokenProvider).state=authFBResult.token;},);

No exemplo acima, o provedor authenticateFBUser depende do appTokenProvider, que ele chama por meio do ProviderReference (ref) que o Riverpod fornece.

Comparando o provedor e o Riverpod

Aqui estão alguns comparações entre Provider e Riverpod:

Exceções de tempo de execução existem com Provider, mas são tratadas e corrigidas com Riverpod Provider não é seguro para compilação enquanto Riverpod está em Provider você não pode declarar múltiplos provedores do mesmo tipo, enquanto em Riverpod , você pode fazer isso sem substituir os outros. Você pode declarar o provedor e sua classe sem espalhar o arquivo raiz do aplicativo em Riverpod. Em Riverpod, os provedores são declarados globalmente e podem ser usados ​​em qualquer lugar no aplicativo usando o widget Consumer ou context.read No Provider, a dependência pode levar a um código terrivelmente aninhado, enquanto no Riverpod é fácil um provedor consumir outro usando ProviderReference

Conclusão

Como mencionei anteriormente, o Riverpod é o sucessor do Provider, e o y foram ambos criados por Remi Rousselet. A Riverpod pode ser vista como um provedor sem as deficiências; ele corrigiu muitas falhas que o Provider tinha.

No entanto, como afirmado anteriormente, cada pacote de gerenciamento de estado tem seus altos e baixos, e tudo depende do seu caso de uso específico. Espero que este post tenha fornecido as comparações necessárias para tomar uma decisão adequada entre as duas opções.