Criando um Sistema de Gerenciamento de Estado Avançado com Riverpod no Flutter

Introdução

Gerenciar estado é uma das tarefas mais importantes e complexas no desenvolvimento de aplicativos Flutter. Uma solução moderna e poderosa é o uso do Riverpod, um pacote que oferece uma abordagem reativa, eficiente e altamente testável para lidar com o estado em Flutter.

Neste tutorial, você aprenderá a configurar o Riverpod em um projeto Flutter, a gerenciar estados simples e complexos e a lidar com cenários avançados como notifiers, state persistence, e depurações avançadas.

1. Por que usar o Riverpod?

O Riverpod traz diversas vantagens sobre outras soluções de gerenciamento de estado, como o Provider. Entre os benefícios estão:

  • Imutabilidade: Facilita o rastreamento e depuração.
  • Escopo limitado: Provedores podem ser descartados automaticamente quando não são mais necessários.
  • Melhor performance: Apenas os widgets necessários são reconstruídos.
  • Testabilidade: Separação clara da lógica de negócios.

2. Configurando o Riverpod

Antes de começar, adicione o pacote ao seu projeto Flutter:


dependencies:
  flutter_riverpod: ^2.0.0

Agora, configure o Riverpod no arquivo principal:


import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomeScreen(),
    );
  }
}

3. Criando um Provedor Simples

Vamos criar um provedor simples para gerenciar um contador:


import 'package:flutter_riverpod/flutter_riverpod.dart';

// Definindo o provedor
final counterProvider = StateProvider((ref) => 0);

Agora, no widget, podemos consumir o provedor:


class HomeScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final counter = ref.watch(counterProvider);

    return Scaffold(
      appBar: AppBar(title: const Text('Riverpod Example')),
      body: Center(
        child: Text(
          'Contador: \$counter',
          style: const TextStyle(fontSize: 24),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(counterProvider.notifier).state++,
        child: const Icon(Icons.add),
      ),
    );
  }
}

4. Trabalhando com Notifiers

Os notifiers permitem gerenciar estados mais complexos:


class CounterNotifier extends StateNotifier {
  CounterNotifier() : super(0);

  void increment() => state++;
  void decrement() => state--;
}

final counterNotifierProvider = StateNotifierProvider((ref) {
  return CounterNotifier();
});

No widget, você pode consumir o counterNotifierProvider da seguinte forma:


class AdvancedCounterScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final counter = ref.watch(counterNotifierProvider);

    return Scaffold(
      appBar: AppBar(title: const Text('Advanced Counter')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'Contador: \$counter',
              style: const TextStyle(fontSize: 24),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                IconButton(
                  onPressed: () => ref.read(counterNotifierProvider.notifier).decrement(),
                  icon: const Icon(Icons.remove),
                ),
                IconButton(
                  onPressed: () => ref.read(counterNotifierProvider.notifier).increment(),
                  icon: const Icon(Icons.add),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

5. Persistindo o Estado

Para persistir o estado entre reinicializações do aplicativo, você pode usar pacotes como shared_preferences. Aqui está um exemplo de integração:


class PersistentCounterNotifier extends StateNotifier {
  PersistentCounterNotifier() : super(0);

  Future loadFromStorage() async {
    final prefs = await SharedPreferences.getInstance();
    state = prefs.getInt('counter') ?? 0;
  }

  Future saveToStorage() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setInt('counter', state);
  }

  void increment() {
    state++;
    saveToStorage();
  }

  void decrement() {
    state--;
    saveToStorage();
  }
}

Conclusão

O Riverpod é uma ferramenta poderosa e flexível para gerenciar estados no Flutter. Este tutorial abordou desde conceitos básicos até cenários mais avançados, como notifiers e persistência de estado. Com isso, você terá uma base sólida para implementar gerenciamentos de estado eficientes em seus projetos.