Skip to main content

Singleton | Flutter

  • Singleton | Flutter

🧩 1. ✅ O padrão clássico com factory + _internal()

Essa é a forma mais comum e idiomática em Dart. Você cria uma instância estática e faz o construtor factory sempre retornar a mesma.

class MySingleton {
// 🔹 Instância única criada logo na inicialização
static final MySingleton _instance = MySingleton._internal();

// 🔹 Construtor factory que retorna sempre a mesma instância
factory MySingleton() {
return _instance;
}

// 🔹 Construtor privado (ninguém fora da classe pode usar)
MySingleton._internal();

// 🔹 Atributos e métodos normais
int counter = 0;

void increment() {
counter++;
print('Contador: $counter');
}
}

Uso:

final a = MySingleton();
final b = MySingleton();

print(identical(a, b)); // true ✅ (mesma instância)

💡 Essa é exatamente a estrutura que usamos no BannerAdManager.


🧱 2. ✅ Com static get instance (forma alternativa mais explícita)

Às vezes, para deixar o código mais legível, você pode preferir usar um getter estático:

class MySingleton {
MySingleton._(); // construtor privado

static final MySingleton _instance = MySingleton._();

static MySingleton get instance => _instance;

void hello() => print('Olá do singleton!');
}

Uso:

MySingleton.instance.hello();

📘 É o mesmo conceito, só muda a sintaxe (e muitos acham mais claro).


⚙️ 3. 🧠 Com inicialização sob demanda (lazy singleton)

Se a criação da instância for “cara” (demorada ou pesada), você pode criar só quando for realmente usada:

class MySingleton {
static MySingleton? _instance;

MySingleton._();

static MySingleton get instance {
_instance ??= MySingleton._(); // cria só na primeira vez
return _instance!;
}

void sayHi() => print('Oi!');
}

Uso:

MySingleton.instance.sayHi();

💡 Ideal se o objeto só for usado em certos momentos do app.


🚀 4. Com injeção de dependência (GetIt, Provider, Riverpod)

Em apps grandes, o singleton geralmente é gerenciado por um container de dependências. Por exemplo, com o GetIt:

import 'package:get_it/get_it.dart';

final getIt = GetIt.instance;

class ApiService {
void fetch() => print('Buscando dados...');
}

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

void main() {
setup();

final api = getIt<ApiService>();
api.fetch(); // ✅ sempre a mesma instância
}

✅ Vantagem: você centraliza todos os singletons e pode trocar implementações em testes (mock).


💡 Dica prática

  • Use o padrão clássico (factory) para gerenciadores pequenos, como BannerAdManager, UserSession, ConfigService.
  • Use GetIt ou Riverpod se o app tiver muitas dependências globais.
  • Nunca use static puro com variáveis mutáveis expostas — prefira encapsular tudo dentro de uma classe singleton.

🎯 Resumo

TipoExemploQuando usar
factory + _internal()MySingleton()Padrão mais comum e direto
static get instanceMySingleton.instanceMais explícito e legível
Lazy singletoncria sob demandaQuando inicialização é pesada
GetIt / Provider / Riverpodvia injeçãoApps médios/grandes com várias dependências