Os 15 tops packages de flutter

🏗️ Gerenciamento de Estado e Arquitetura

1. Riverpod

O sucessor espiritual do Provider. É reativo, seguro contra erros em tempo de compilação e não depende do BuildContext.

  • Exemplo: final counterProvider = StateProvider((ref) => 0);

  • Utilidade: Gerenciamento de estado global e injeção de dependências.

// Definição do provedor
final counterProvider = StateProvider((ref) => 0);

// Uso no Widget
class Home extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);
    return ElevatedButton(
      onPressed: () => ref.read(counterProvider.notifier).state++,
      child: Text('Contagem: $count'),
    );
  }
}

 

2. Flutter BLoC

Implementa o padrão Business Logic Component. Separa a interface da lógica de forma rígida e testável.

  • Exemplo: Uso de BlocBuilder e BlocListener para reagir a estados.

  • Utilidade: Apps de grande escala com fluxos complexos.

// Evento
abstract class CounterEvent {}
class Increment extends CounterEvent {}

// Bloc
class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0) {
    on<Increment>((event, emit) => emit(state + 1));
  }
}

// UI
BlocBuilder<CounterBloc, int>(
  builder: (context, state) => Text('$state'),
);

 

3. GetIt

Um localizador de serviços (Service Locator) extremamente simples e rápido.

  • Exemplo: getIt.registerSingleton<ApiService>(ApiService());

  • Utilidade: Acessar objetos e instâncias de qualquer lugar do código.

final getIt = GetIt.instance;

void setup() {
  getIt.registerSingleton<ApiService>(ApiService());
}

// Acessando em qualquer lugar:
final api = getIt<ApiService>();

 


🗄️ Persistência de Dados (Local e Nuvem)

4. Drift

Banco de dados SQL potente e reativo. Como discutido anteriormente, é ideal para dados relacionais complexos.

  • Exemplo: Permite escrever queries SQL puras com segurança de tipos em Dart.

  • Utilidade: Apps “Offline-First” com tabelas interligadas.

class Tasks extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 1, max: 50)();
}

// Query
final allTasks = await select(tasks).get();

 

5. Isar

O banco NoSQL mais rápido para Flutter, otimizado para alta performance e múltiplos núcleos.

  • Exemplo: Consultas avançadas com filtros nativos: isar.users.filter().nameStartsWith("A").findAll();.

  • Utilidade: Armazenar grandes volumes de objetos com rapidez extrema.

@collection
class User {
  Id id = Isar.autoIncrement;
  late String name;
}

// Inserindo
await isar.writeTxn(() => isar.users.put(newUser));

// Consultando
final users = await isar.users.filter().nameStartsWith("Jo").findAll();

 

6. Cloud Firestore

A solução de nuvem do Firebase para sincronização em tempo real entre dispositivos.

  • Exemplo: collection('chats').snapshots() para ouvir mensagens novas instantaneamente.

  • Utilidade: Apps colaborativos, chats e dashboards em tempo real.

StreamBuilder(
  stream: FirebaseFirestore.instance.collection('mensagens').snapshots(),
  builder: (context, snapshot) {
    if (!snapshot.hasData) return CircularProgressIndicator();
    return ListView(children: snapshot.data.docs.map((doc) => Text(doc['texto'])));
  },
);

 


🌐 Networking e APIs

7. Dio

Um cliente HTTP poderoso com suporte a interceptadores, cancelamento de requisições e upload de arquivos.

  • Exemplo: dio.get('/user', queryParameters: {'id': 123});

  • Utilidade: O padrão ouro para consumo de APIs REST no Flutter.

final dio = Dio();

try {
  final response = await dio.get('https://api.exemplo.com/dados');
  print(response.data);
} on DioException catch (e) {
  print(e.message);
}

 

8. Freezed

Gerador de código para classes de dados imutáveis, uniões (unions) e clonagem.

  • Exemplo: Cria automaticamente métodos copyWith e fromJson.

  • Utilidade: Elimina código repetitivo (boilerplate) em modelos e estados.

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

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}

 


🎨 Interface e Animações

9. Lottie

Renderiza animações do Adobe After Effects exportadas como JSON.

  • Exemplo: Lottie.asset('assets/animation.json');

  • Utilidade: Adicionar animações complexas e leves sem perda de qualidade.

Lottie.asset('assets/success_animation.json', width: 200, height: 200);

 

10. Flutter Spinkit

Uma coleção de indicadores de carregamento (loaders) estilizados.

  • Exemplo: SpinKitFadingCircle(color: Colors.white, size: 50.0);

  • Utilidade: Melhorar o feedback visual durante requisições assíncronas.

SpinKitRotatingCircle(
  color: Colors.blue,
  size: 50.0,
);

 

11. Shimmer

Cria aquele efeito de “carregamento brilhante” que vemos no Facebook ou Instagram.

  • Exemplo: Envolver widgets em um Shimmer.fromColors.

  • Utilidade: Placeholder elegante enquanto os dados reais não carregam.

Shimmer.fromColors(
  baseColor: Colors.grey[300]!,
  highlightColor: Colors.grey[100]!,
  child: Container(width: 200, height: 20, color: Colors.white),
);

 


🛠️ Ferramentas Utilitárias e Segurança

12. Flutter Secure Storage

Armazena dados sensíveis (como JWT ou tokens) usando Keychain (iOS) e Keystore (Android).

  • Exemplo: storage.write(key: 'jwt', value: token);.

  • Utilidade: Proteção de credenciais que não devem ficar no SQLite ou SharedPreferences.

final storage = FlutterSecureStorage();

// Escrever
await storage.write(key: 'auth_token', value: 'meu_jwt_secreto');

// Ler
String? token = await storage.read(key: 'auth_token');

 

13. Go Router

O pacote oficial para navegação declarativa, lidando facilmente com rotas aninhadas e Deep Linking.

  • Exemplo: Define rotas de forma simples: GoRoute(path: '/user/:id', builder: ...).

  • Utilidade: Navegação robusta, especialmente importante para Flutter Web.

final _router = GoRouter(
  routes: [
    GoRoute(
      path: '/perfil/:userId',
      builder: (context, state) => ProfileScreen(id: state.pathParameters['userId']!),
    ),
  ],
);

 

14. Intl

Ferramenta para internacionalização e localização (tradução de textos e formatos de data/moeda).

  • Exemplo: DateFormat.yMMMd().format(DateTime.now());

  • Utilidade: Essencial para apps que desejam atingir o mercado global.

String preco = NumberFormat.simpleCurrency(locale: 'pt_BR').format(1500.50);
// Resultado: R$ 1.500,50

 

15. Flutter Dotenv

Carrega variáveis de ambiente de um arquivo .env.

  • Exemplo: dotenv.env['BASE_URL'];.

  • Aviso de Segurança: Como vimos, use apenas para configurações públicas (como URLs de teste). Nunca coloque segredos de faturamento ou chaves privadas aqui, pois podem ser extraídos do binário.

// No arquivo .env: BASE_URL=https://api.meuapp.com
await dotenv.load(fileName: ".env");
String url = dotenv.env['BASE_URL'] ?? 'fallback.com';

🛡️ Lembrete de Segurança Importante (Reforço)

Como vimos nos textos anteriores sobre segurança em Flutter:

  • Use o Flutter Secure Storage para tokens e segredos do usuário.

  • Nunca coloque chaves de API pagas (como Google Maps ou Stripe) no seu arquivo .env ou direto no código se for para produção.

  • Em vez disso, faça o app chamar o seu Backend, e o seu backend faz a chamada para a API paga protegendo a chave. Se a chave estiver no .env, ela pode ser extraída via engenharia reversa do APK, gerando faturas altíssimas para você!

📊 Tabela de Decisão Rápida

Objetivo Sugestão
Escalabilidade Flutter BLoC + Riverpod
Velocidade Local Isar
Sincronização Nuvem Firestore
Segurança de Tokens Flutter Secure Storage

 

Gerenciador de Finanças Pessoais

Este exemplo mostra como os pacotes se conectam desde a segurança do token até à exibição reativa dos dados.

📦 Os 7 Packages Utilizados:

  1. Riverpod: Controlo de estado e injeção de dependências.

  2. Dio: Chamadas HTTP para a API de cotações.

  3. Drift: Base de dados SQL local para guardar transações.

  4. Flutter Secure Storage: Para guardar a chave privada do utilizador.

  5. Freezed: Modelos de dados imutáveis com JSON.

  6. Intl: Formatação de moeda (R$) e datas.

  7. Flutter Spinkit: Feedback visual de carregamento.

1. O Modelo de Dados (Freezed)

Define a estrutura de uma transação financeira.

import 'package:freezed_annotation/freezed_annotation.dart';
part 'transaction.freezed.dart';
part 'transaction.g.dart';

@freezed
class Transaction with _$Transaction {
  const factory Transaction({
    required int id,
    required String description,
    required double value,
    required DateTime date,
  }) = _Transaction;

  factory Transaction.fromJson(Map<String, dynamic> json) => _$TransactionFromJson(json);
}

2. Base de Dados Local (Drift)

Cria a tabela e a lógica de persistência local.

import 'package:drift/drift.dart';
// ... imports do drift ...

class LocalTransactions extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get description => text()();
  RealColumn get value => real()();
  DateTimeColumn get date => dateTime()();
}

3. Lógica de Negócio e API (Riverpod + Dio + SecureStorage)

Este “Provider” gere tudo: verifica o token, vai à API buscar cotações e lê do banco local.

final financeProvider = StateNotifierProvider<FinanceNotifier, AsyncValue<List<Transaction>>>((ref) {
  return FinanceNotifier();
});

class FinanceNotifier extends StateNotifier<AsyncValue<List<Transaction>>> {
  final _dio = Dio();
  final _storage = const FlutterSecureStorage();

  FinanceNotifier() : super(const AsyncValue.loading()) {
    _init();
  }

  Future<void> _init() async {
    try {
      // 1. Recuperar chave de segurança
      final apiKey = await _storage.read(key: 'user_api_key');
      
      // 2. Exemplo de chamada API com Dio
      final response = await _dio.get('https://api.exemplo.com/v1/finance?key=$apiKey');
      
      // 3. Mapear dados para o modelo Freezed
      final List data = response.data['transactions'];
      final transactions = data.map((e) => Transaction.fromJson(e)).toList();

      state = AsyncValue.data(transactions);
    } catch (e, st) {
      state = AsyncValue.error(e, st);
    }
  }
}

4. A Interface (Spinkit + Intl)

A parte visual que consome o estado reativo.

import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:intl/intl.dart';

class FinanceHomePage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final state = ref.watch(financeProvider);

    return Scaffold(
      appBar: AppBar(title: const Text('Meu Extrato')),
      body: state.when(
        loading: () => const Center(
          child: SpinKitDoubleBounce(color: Colors.green, size: 50.0), // Spinkit
        ),
        error: (err, _) => Center(child: Text('Erro ao carregar: $err')),
        data: (transactions) => ListView.builder(
          itemCount: transactions.length,
          itemBuilder: (context, index) {
            final item = transactions[index];
            
            // Intl: Formatação para Real Brasileiro e Data
            final currency = NumberFormat.simpleCurrency(locale: 'pt_BR').format(item.value);
            final date = DateFormat.yMd('pt_BR').format(item.date);

            return ListTile(
              leading: const Icon(Icons.monetization_on, color: Colors.green),
              title: Text(item.description),
              subtitle: Text(date),
              trailing: Text(currency, style: const TextStyle(fontWeight: FontWeight.bold)),
            );
          },
        ),
      ),
    );
  }
}

🚀 Por que este projeto é “nível profissional”?

  1. Segurança: O token de acesso não está “hardcoded” nem em ficheiros de texto simples; está no Secure Storage (encriptado pelo SO).

  2. Performance: O Drift permite que o app funcione offline. O Dio lida com timeouts e interceptores de forma eficiente.

  3. Manutenção: Se a API mudar um campo, o Freezed ajuda a identificar o erro rapidamente. O Riverpod garante que a UI só reconstrói quando o dado realmente muda.

  4. UX: O utilizador nunca vê uma tela branca ou travada, graças ao Spinkit e ao estado AsyncValue.

Dica Final: Para colocar este projeto a funcionar, não se esqueça de correr o comando dart run build_runner build no terminal para gerar os ficheiros automáticos do Drift e do Freezed!

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