Flutter gerenciamento de estado simples e complexo usando Riverpod

Tempo de leitura: 4 minutes

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.

  1. StateProvider
  2. StateNotifierProvider
  3. ChangeNotifierProvider

 

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

  1. Se você deseja gerenciar apenas um único estado sem lógica de negócios ou efeitos colaterais, você pode usar StateProvider.
  2. Se você tiver um ou vários estados com lógica de negócios ou efeito colateral, poderá usar StateNotifierProvider (recomendado) ou ChangeNotifierProvider (não recomendado)