Como usar o RiverPod no Flutter
Tempo de leitura: 3 minutes
- É semelhante ao Provider e é seguro para compilação e testável.
- O Riverpod é inspirado no Provider, mas resolve alguns de seus principais problemas, como oferecer suporte a vários provedores do mesmo tipo; aguardando provedores assíncronos; adicionando provedores de qualquer lugar.
- Não há mais necessidade de pular entre seu main.dart e seus arquivos de interface do usuário.
- Coloque o código do seu estado compartilhado onde ele pertence, seja em um pacote separado ou ao lado do Widget que precisa dele, sem perder a testabilidade.
Os provedores são a parte mais importante de um aplicativo Riverpod. Um provedor é um objeto que encapsula um pedaço de estado e permite ouvir esse estado.
enum Status { initial, loading, success, } class RiverpodProvider extends StateNotifier<Status> { RiverpodProvider() : super(Status.initial); Future<void> fetchData() async { state = Status.loading; await Future.delayed(const Duration(seconds: 2)); state = Status.success; } } final riverpodProvider = StateNotifierProvider.autoDispose((ref) => RiverpodProvider());
Na IU temos:
class RiverpodPage extends StatelessWidget { static const route = 'riverpod-page'; const RiverpodPage({super.key}); @override Widget build(BuildContext context) { return const ProviderScope( child: HomeRiverpod(), ); } }
Para que os widgets possam ler os provedores, precisamos agrupar o aplicativo inteiro em um widget “ProviderScope”. É aqui que o estado de nossos provedores será armazenado.
class HomeRiverpod extends ConsumerWidget { const HomeRiverpod({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final data = ref.read(riverpodProvider.notifier); return Scaffold( appBar: AppBar(title: const Text('Riverpod Page')), //É uma boa prática colocar seus widgets de consumidor o mais fundo possível na árvore. //Você não deseja reconstruir grandes porções da interface do usuário apenas porque algum detalhe em algum lugar foi alterado. body: Consumer( builder: (context, ref, child) { final state = ref.watch(riverpodProvider); if (state == Status.initial) { return const Center(child: Text('Press the Button')); } if (state == Status.loading) { return const Center(child: CircularProgressIndicator()); } if (state == Status.success) { return const Center(child: Text('Success')); } return Container(); }, ), floatingActionButton: Column( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: <Widget>[ FloatingActionButton( child: const Icon(Icons.play_arrow), onPressed: () => data.fetchData(), ), ], ), ); } }
Usando ref para interagir com provedores
Existem três usos principais para “ref”:
- Obter o valor de um provedor e ouvir as alterações, de modo que, quando esse valor mudar, isso reconstruirá o widget ou provedor que assinou o valor. Isso é feito usando ref.watch
- Adicionar um ouvinte em um provedor para executar uma ação, como navegar para uma nova página ou mostrar um modal sempre que esse provedor for alterado.
Isso é feito usando ref.listen. - Obter o valor de um provedor ignorando as alterações. Isso é útil quando precisamos do valor de um provedor em um evento como “on click”. Isso é feito usando ref.read.
E o resultado é o seguinte:
Prós
- Riverpod é estável e mantido ativamente.
- O Riverpod não depende diretamente da árvore de widgets. Os provedores são declarados globalmente e podem ser usados em qualquer lugar do aplicativo
- Escreva código testável e mantenha a lógica fora da árvore de widgets
Contras
- O Riverpod oferece muita liberdade para implementar o estado em seu aplicativo. isso pode ser um desafio para novos desenvolvedores escolherem a melhor abordagem.
- Ele encoraja um antipadrão ruim de espalhar o estado compartilhado por toda a sua árvore de widgets. Isso pode tornar o código muito difícil de encontrar (não centralizado) e dificultar a depuração, pois há cadeias de dependência excessivas e acoplamentos entre provedores.