Flutter gerenciamento de estado simples e complexo usando Riverpod
No Flutter, Riverpod é uma biblioteca popular de gerenciamento de estado que oferece uma maneira simples e concisa de gerenciar o estado em seu aplicativo. Ele fornece diferentes provedores para lidar com o estado, incluindo StateProvider
, StateNotifierProvider
e ChangeNotifierProvider
. Vamos explorar como você pode usar o Riverpod com esses provedores para gerenciamento de estado simples e complexo.
No final deste artigo, você será capaz de gerenciar seu estado em flutter com fluência, irei cobrir.
- StateProvider
- StateNotifierProvider
- ChangeNotifierProvider
Conteudo
StateProvider
caso de uso: StateProvider
é usado para gerenciar valores de estado simples no Flutter. Ele permite definir um valor de estado e acessá-lo a partir de vários widgets. Isso facilita o compartilhamento e a atualização do estado em diferentes partes do seu aplicativo. Suponha que tenhamos um estado muito simples, como verdadeiro/falso, ou queiramos gerenciar um único estado, quando pudermos usar StateProvider
Exemplo:
Aqui faremos um contador simples, gerenciaremos apenas o estado de contagem única
import 'package:hooks_riverpod/hooks_riverpod.dart'; final counterProvider = StateProvider<int>((ref) => 0);
import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import '../State/stateProviderState.dart'; class StateProviderPage extends HookConsumerWidget { const StateProviderPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final counter = ref.watch(counterProvider); return Scaffold( appBar: AppBar( title: const Text('Counter stateProvider'), ), body: Center( child: Column( children: [ Text('$counter'), Row( children: [ ElevatedButton( onPressed: () => ref.read(counterProvider.notifier).state++, child: const Text("increase")), ElevatedButton( onPressed: () => ref.read(counterProvider.notifier).state--, child: const Text("decrease")), ], ) ], )), ); } }
StateNotifierProvider
Recomendado para gerenciar vários estados
caso de uso: StateNotifierProvider
pode ser usado para gerenciar estados únicos ou múltiplos. você também pode lidar com sua lógica de negócios e efeitos colaterais dentro da classe XYZ estende StateNotifier(){}
Exemplo: (estado único)
import 'package:hooks_riverpod/hooks_riverpod.dart'; final counterStateNotifierProvider = StateNotifierProvider<Counter, int>((ref) => Counter()); class Counter extends StateNotifier<int> { Counter() : super(0) { print('Counter object created'); } void increment() { state++; } void decrement() { state--; } }
import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:sizer/sizer.dart'; import '../../../state/StateNotifierProviderStateSingleVariable.dart'; class StateNotifierProviderPageSingleVariable extends HookConsumerWidget { const StateNotifierProviderPageSingleVariable({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final counter = ref.watch(counterStateNotifierProvider); return Scaffold( appBar: AppBar( title: const Text('Counter StateNotifierProvider'), ), body: Center( child: Column( children: [ Text('$counter'), Row( children: [ ElevatedButton( onPressed: () => ref .read(counterStateNotifierProvider.notifier) .increment(), child: const Text("+")), SizedBox( width: 5.w, ), ElevatedButton( onPressed: () => ref .read(counterStateNotifierProvider.notifier) .decrement(), child: const Text("-")), ], ) ], )), ); } }
Exemplo: (estado múltiplo)
import 'package:hooks_riverpod/hooks_riverpod.dart'; final counterStateProvider = StateNotifierProvider<CounterState, Counter>( (ref) => CounterState(), ); //immutable class class Counter { final int counter1; final int counter2; Counter({required this.counter1, required this.counter2}) { print("child object create"); } Counter copyWith({int? counter1, int? counter2}) { return Counter( counter1: counter1 ?? this.counter1, counter2: counter2 ?? this.counter2, ); } } class CounterState extends StateNotifier<Counter> { CounterState() : super(Counter(counter1: 0, counter2: 0)); void incrementCounter1() { state = state.copyWith(counter1: state.counter1 + 1); } void decrementCounter1() { state = state.copyWith(counter1: state.counter1 - 1); } void incrementCounter2() { state = state.copyWith(counter2: state.counter2 + 1); } void decrementCounter2() { state = state.copyWith(counter2: state.counter2 - 1); } }
import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import '../../../state/StateNotifierProviderStateMultipleVariable.dart'; class StateNotifierProviderPageMultipleVariable extends HookConsumerWidget { const StateNotifierProviderPageMultipleVariable({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final counterState = ref.watch(counterStateProvider); return Scaffold( appBar: AppBar( title: const Text('Counter StateNotifierProvider'), ), body: Center( child: Column( children: [ Text('Counter 1: ${counterState.counter1}'), ElevatedButton( onPressed: () { ref.read(counterStateProvider.notifier).incrementCounter1(); }, child: const Text('Increment Counter 1'), ), ElevatedButton( onPressed: () { ref.read(counterStateProvider.notifier).decrementCounter1(); }, child: const Text('Decrement Counter 1'), ), const SizedBox(height: 16), Text('Counter 2: ${counterState.counter2}'), ElevatedButton( onPressed: () { ref.read(counterStateProvider.notifier).incrementCounter2(); }, child: const Text('Increment Counter 2'), ), ElevatedButton( onPressed: () { ref.read(counterStateProvider.notifier).decrementCounter2(); }, child: const Text('Decrement Counter 2'), ), ], )), ); } }
final xyzStateProvider = StateNotifierProvider<xyzState, xyz>( (ref) => xyzState(), ); //immutable class class xyz{ //Gerencie todo o seu estado aqui } class xyzState extends StateNotifier<xyz> { CounterState() : super(xyz()); //sua lógica de negócios }
ChangeNotifierProvider
Não recomendado por Riverpod
caso de uso: ChangeNotifierProvider
pode ser usado para gerenciar estados únicos ou múltiplos. você também pode lidar com sua lógica de negócios e efeitos colaterais dentro da classe XYZ estende ChangeNotifier(){}
Exemplo: (estado único)
import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; final counterChangeNotifierProvider = ChangeNotifierProvider<Counter>((ref) => Counter()); class Counter extends ChangeNotifier { Counter() { print('Counter object created'); } int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } void decrement() { _count--; notifyListeners(); } }
import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import '../../../state/ChangeNotifierProviderStateSingleVariable.dart'; class ChangeNotifierProviderSingleVariablePage extends HookConsumerWidget { const ChangeNotifierProviderSingleVariablePage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final counter = ref.watch(counterChangeNotifierProvider); return Scaffold( appBar: AppBar( title: const Text('Counter ChangeNotifierProvider'), ), body: Center( child: Column( children: [ Text('${counter.count}'), Row( children: [ ElevatedButton( onPressed: () => ref .read(counterChangeNotifierProvider.notifier) .increment(), child: const Text("+")), ElevatedButton( onPressed: () => ref .read(counterChangeNotifierProvider.notifier) .decrement(), child: const Text("-")), ], ) ], )), ); } }
Exemplo: (estado múltiplo)
import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; final counterChangeNotifierProvider = ChangeNotifierProvider<Counter>((ref) => Counter()); class Counter extends ChangeNotifier { Counter() { print('Counter object created'); } int _count1 = 0; int _count2 = 0; int get count1 => _count1; int get count2 => _count2; void increment1() { _count1++; notifyListeners(); } void decrement1() { _count1--; notifyListeners(); } void increment2() { _count2++; notifyListeners(); } void decrement2() { _count2--; notifyListeners(); } }
import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:sizer/sizer.dart'; import '../../../state/ChangeNotifierProviderStateMultipleVariable.dart'; class ChangeNotifierProviderMultipleVariablePage extends HookConsumerWidget { const ChangeNotifierProviderMultipleVariablePage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final counter = ref.watch(counterChangeNotifierProvider); return Scaffold( appBar: AppBar( title: const Text('Counter ChangeNotifierProvider'), ), body: Center( child: Column( children: [ Column( children: [ Text('${counter.count1}'), Row( children: [ ElevatedButton( onPressed: () => ref .read(counterChangeNotifierProvider.notifier) .increment1(), child: const Text("+")), ElevatedButton( onPressed: () => ref .read(counterChangeNotifierProvider.notifier) .decrement1(), child: const Text("-")), ], ) ], ), Column( children: [ Text('${counter.count2}'), Row( children: [ ElevatedButton( onPressed: () => ref .read(counterChangeNotifierProvider.notifier) .increment2(), child: const Text("+")), ElevatedButton( onPressed: () => ref .read(counterChangeNotifierProvider.notifier) .decrement2(), child: const Text("-")), ], ) ], ), ], )), ); } }
Conclusão
- Se você deseja gerenciar apenas um único estado sem lógica de negócios ou efeitos colaterais, você pode usar
StateProvider
. - Se você tiver um ou vários estados com lógica de negócios ou efeito colateral, poderá usar
StateNotifierProvide
r (recomendado) ouChangeNotifierProvider
(não recomendado)