Comunicação entre widgets sem callbacks usando Notification
Normalmente, quando um widget precisa avisar outro sobre alguma ação, acabamos recorrendo a callbacks, Provider, EventBus ou até mesmo um GlobalKey.
Mas existe uma alternativa nativa do Flutter que muita gente esquece: Notification.
Ela permite que um widget envie um evento para seus ancestrais sem conhecer quem irá tratá-lo.
Exemplo prático
Imagine um aplicativo bancário.
O usuário tenta realizar uma transferência.
O widget responsável pela transferência percebe que a operação exige autenticação por PIN.
Ao invés de conhecer o Scaffold, chamar um callback ou acessar algum serviço global, ele apenas dispara uma Notification.
final class RequestPinNotification extends Notification {
final _completer = Completer<bool>();
static Future<bool> request(BuildContext context) {
final notification = RequestPinNotification();
notification.dispatch(context);
return notification._completer.future;
}
void complete(bool value) => _completer.complete(value);
}
Quando precisar autenticar:
onTap: () async {
final authenticated = await RequestPinNotification.request(context);
if (authenticated) {
// continua
}
}
Na raiz da tela ou do app:
NotificationListener<RequestPinNotification>(
onNotification: (notification) async {
final success = await showModalBottomSheet<bool>(
context: context,
builder: (_) => const PinBottomSheet(),
) ??
false;
notification.complete(success);
return true;
},
child: const TransferPage(),
)
Agora qualquer widget dentro da árvore pode solicitar autenticação sem conhecer quem irá exibir o BottomSheet.
TransferButton
↓
TransferForm
↓
TransferPage
↓
NotificationListener
Todo o acoplamento desaparece.
Outro caso muito útil: Analytics
Imagine que vários componentes da aplicação precisem registrar eventos.
final class TrackEventNotification extends Notification {
final String name;
const TrackEventNotification(this.name);
}
Ao invés de injetar Analytics em cada widget:
TrackEventNotification(
name: 'buy_button_clicked',
).dispatch(context);
Na raiz:
NotificationListener<TrackEventNotification>(
onNotification: (notification) {
analytics.logEvent(
notification.name,
);
return true;
},
child: App(),
)
Os widgets apenas informam o que aconteceu.
Quem decide enviar para Firebase, Mixpanel, Sentry ou outra ferramenta fica completamente separado.
Quando usar
O Notification funciona muito bem para eventos que “sobem” na árvore:
- abrir BottomSheet
- solicitar autenticação
- analytics
- logging
- feedback visual
- comandos para o Scaffold
- telemetria
Quando não usar
Ele não substitui gerenciamento de estado.
Se você precisa compartilhar dados, estados reativos ou sincronizar telas, soluções como Riverpod, Bloc ou ValueNotifier continuam sendo mais adequadas.
Pense no Notification como um evento de UI, e não como um estado da aplicação.
Conclusão
O sistema de Notification é um recurso pouco explorado do Flutter, mas extremamente útil para eliminar callbacks desnecessários e reduzir o acoplamento entre widgets.
Sempre que um widget precisar apenas dizer “algo aconteceu”, vale considerar uma Notification antes de criar mais uma dependência entre componentes.
Outras ideias de exemplos
Além do BottomSheet, você pode usar exatamente o mesmo conceito para:
- ✅ Solicitar login quando uma API retornar 401 Unauthorized.
- ✅ Abrir um diálogo de confirmação antes de excluir um item.
- ✅ Mostrar um
SnackBarglobal. - ✅ Registrar eventos de Analytics.
- ✅ Medir tempo de uso de uma tela.
- ✅ Atualizar um contador na
AppBar. - ✅ Fechar um Drawer.
- ✅ Disparar um efeito de celebração (confetes, animações) quando uma ação for concluída.
Na minha opinião, o exemplo de autenticação via BottomSheet é o mais forte, porque mostra um benefício claro: qualquer widget profundo na árvore pode solicitar autenticação sem depender de callbacks ou conhecer a estrutura da tela. Isso evidencia muito bem o propósito do Notification.