Top 10 Packages Avançados para Flutter

1. Riverpod

Muito mais que um gerenciador de estado, é um framework de Injeção de Dependência reativo.

  • Características: Captura erros em tempo de compilação, permite acesso ao estado sem BuildContext e facilita testes unitários.

  • Exemplo Prático:

    final userDataProvider = FutureProvider((ref) => ref.watch(apiProvider).getUser());

2. Freezed

O pacote essencial para Modelagem de Dados e classes imutáveis.

  • Características: Gera automaticamente copyWith, fromJson/toJson e suporte a Sealed Classes (Unions).

  • Exemplo Prático:

    @freezed
    class User with _$User {
      const factory User({required String name, required int age}) = _User;
    }

     

3. Drift

O motor SQL mais avançado (antigo Moor) para persistência de dados offline.

  • Características: Permite escrever queries em Dart puro, oferece migrações automáticas e é totalmente reativo (Streams).

  • Exemplo Prático:

// Seleção reativa de dados
Stream<List<Todo>> watchEntries() => select(todos).watch();

4. GoRouter

A solução padrão para Navegação Declarativa (Router API).

  • Características: Gerencia Deep Linking, rotas aninhadas e redirecionamentos baseados em autenticação.

  • Exemplo Prático:

GoRoute(path: '/details/:id', builder: (context, state) => DetailsPage(id: state.pathParameters['id']!))

5. Auto Route

Um roteador baseado em geração de código focado em segurança de tipos.

  • Características: Gera rotas fortemente tipadas, evitando erros de digitação em strings de caminhos.

  • Exemplo Prático:

context.router.push(UserRoute(id: 10)); // Passagem de argumentos segura

6. Isar

Banco de dados NoSQL ultra rápido, sucessor espiritual do Hive.

  • Características: Suporta transações ACID, consultas complexas, links entre objetos e é otimizado para múltiplos núcleos.

  • Exemplo Prático:

final users = await isar.users.filter().nameStartsWith("Gemini").findAll();

7. Talker

Sistema de Observabilidade e Logs avançado para monitoramento em tempo real.

  • Características: Intercepta logs de rede, erros do Flutter e mensagens de sistema em uma interface visual.

  • Exemplo Prático:

final talker = Talker();
talker.error('Erro crítico na API', exception, stackTrace);

8. Sentry

A ferramenta líder para Monitoramento de Erros e Performance em produção.

  • Características: Reporta crashes automaticamente e fornece “Breadcrumbs” (os passos do usuário antes do erro).

  • Exemplo Prático:

await SentryFlutter.init((options) => options.dsn = 'SUA_DSN_AQUI');

9. Hydrated BLoC

Uma extensão do BLoC que persiste estados automaticamente.

  • Características: Salva o estado do BLoC no disco e o restaura ao reiniciar o app sem código extra.

  • Exemplo Prático:

// O estado do tema é salvo automaticamente ao mudar
@override
ThemeState? fromJson(Map<String, dynamic> json) => ThemeState.fromMap(json);

10. Flutter Hooks

Inspirado no React Hooks, focado em reutilização de lógica de widgets.

  • Características: Elimina o boilerplate de StatefulWidgets como controladores de animação ou texto.

  • Exemplo Prático:

final controller = useTextEditingController(); // Gerido automaticamente

 

📊 Tabela de Comparação e Uso

Package Foco Principal Complexidade Quando Implementar?
Riverpod Gestão de Estado / DI Média Em qualquer projeto profissional.
Freezed Modelagem / Imutabilidade Baixa Sempre que criar classes de dados.
Drift SQL Reativo Alta Apps Offline-First complexos.
Isar NoSQL Performance Média Quando velocidade é a maior prioridade.
GoRouter Navegação Web/Mobile Baixa Apps com navegação complexa.
Sentry Observabilidade Média Antes de publicar o app na loja.

💡 Cenário de Uso Combinado

Em um projeto de alto nível, a arquitetura geralmente se parece com isto:

  1. Modelos: Criados com Freezed para segurança de dados.

  2. Repositórios: Usam Drift ou Isar para cache local.

  3. Comunicação: Riverpod injeta os repositórios nos Widgets.

  4. Navegação: Auto Route ou GoRouter gerencia as transições.

  5. Monitoramento: Sentry e Talker garantem que nada falhe silenciosamente.

Este é um exemplo de arquitetura profissional utilizando o “Trio de Ouro” do Flutter avançado: Riverpod (Estado e DI), GoRouter (Navegação) e Freezed (Modelagem imutável).

Este fluxo simula uma autenticação completa: o estado do utilizador é monitorizado e, caso ele saia (logout), o router redireciona-o automaticamente para a página de Login.

1. Modelagem com Freezed (user_model.dart)

O Freezed garante que o nosso estado seja imutável e fornece métodos como copyWith.

import 'package:freezed_annotation/freezed_annotation.dart';

part 'user_model.freezed.dart';
part 'user_model.g.dart';

@freezed
class AuthState with _$AuthState {
  const factory AuthState.initial() = _Initial;
  const factory AuthState.loading() = _Loading;
  const factory AuthState.authenticated(String email) = _Authenticated;
  const factory AuthState.unauthenticated() = _Unauthenticated;
}

2. Lógica de Estado com Riverpod (auth_provider.dart)

Aqui gerimos a lógica. O Notifier permite-nos expor métodos para login/logout.

import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'auth_provider.g.dart';

@riverpod
class AuthNotifier extends _$AuthNotifier {
  @override
  AuthState build() => const AuthState.unauthenticated();

  Future<void> login(String email, String password) async {
    state = const AuthState.loading();
    await Future.delayed(const Duration(seconds: 2)); // Simula API
    state = AuthState.authenticated(email);
  }

  void logout() {
    state = const AuthState.unauthenticated();
  }
}

3. Navegação Declarativa com GoRouter (router.dart)

O segredo aqui é o refreshListenable. O router “ouve” as mudanças no estado do Riverpod e decide para onde enviar o utilizador.

import 'package:go_router/go_router.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final routerProvider = Provider<GoRouter>((ref) {
  final authState = ref.watch(authNotifierProvider);

  return GoRouter(
    initialLocation: '/login',
    // Redirecionamento Automático
    redirect: (context, state) {
      final isAuth = authState is _Authenticated;
      final isLoggingIn = state.matchedLocation == '/login';

      if (!isAuth && !isLoggingIn) return '/login';
      if (isAuth && isLoggingIn) return '/home';
      return null;
    },
    routes: [
      GoRoute(path: '/login', builder: (context, state) => const LoginPage()),
      GoRoute(path: '/home', builder: (context, state) => const HomePage()),
    ],
  );
});

4. Interface (UI) – Login e Home

Página de Login:

class LoginPage extends ConsumerWidget {
  const LoginPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final state = ref.watch(authNotifierProvider);

    return Scaffold(
      body: Center(
        child: state.maybeWhen(
          loading: () => const CircularProgressIndicator(),
          orElse: () => ElevatedButton(
            onPressed: () => ref.read(authNotifierProvider.notifier).login('dev@flutter.com', '123456'),
            child: const Text('Entrar no App'),
          ),
        ),
      ),
    );
  }
}

Página Home:

class HomePage extends ConsumerWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      appBar: AppBar(title: const Text('Dashboard')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => ref.read(authNotifierProvider.notifier).logout(),
          child: const Text('Sair (Logout)'),
        ),
      ),
    );
  }
}

💎 Vantagens desta Abordagem Avançada

  1. Redirecionamento Centralizado: Não precisas de chamar context.push() manualmente após o login. O router detecta que o estado mudou para authenticated e move o utilizador sozinho.

  2. Segurança de Estado: Com o Freezed, é impossível o app estar em “Loading” e “Authenticated” ao mesmo tempo, pois as Unions são exclusivas.

  3. Testabilidade: Podes testar o AuthNotifier e o GoRouter separadamente sem precisar de emuladores, injetando mocks no ProviderContainer.

  4. Sincronização: Se o token expirar (mudança para unauthenticated), o utilizador é expulso da Home instantaneamente, de qualquer parte do app.

Este padrão é o que empresas como a Nubank, Airbnb e BMW utilizam nas suas aplicações Flutter de larga escala. Gostarias de ver como integrar o Sentry neste fluxo para capturar erros de login automaticamente?

Please follow and like us:
error0
fb-share-icon
Tweet 20
fb-share-icon20