AirListener
AirListener is a widget designed to execute side-effects (like navigation, showing SnackBars, or opening dialogs) in response to state changes, without rebuilding your UI.
Why use AirListener?
Section titled “Why use AirListener?”In Flutter, the build method should be pure and focused only on drawing the interface. Mixing side-effects inside builders like AirView using addPostFrameCallback is an anti-pattern that can lead to duplicated dialogs or unexpected routing when the widget rebuilds for other reasons.
AirListener strictly observes state dependencies and triggers a callback when any of them change, keeping your build methods pristine.
Basic Usage
Section titled “Basic Usage”Wrap your UI or the specific section that needs side-effects with an AirListener. Provide a list of AirStateKeys to listen to, and define your side-effects inside the listener callback.
import 'package:flutter/material.dart';import 'package:air_framework/air_framework.dart';
class LoginPage extends StatelessWidget { @override Widget build(BuildContext context) { return AirListener( listen: [ AuthFlows.isAuthenticated, AuthFlows.error ], listener: (context) { // 1. Reacting to authentication success if (AuthFlows.isAuthenticated.value) { context.go('/'); }
// 2. Reacting to errors if (AuthFlows.error.value != null && AuthFlows.error.value!.isNotEmpty) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(AuthFlows.error.value!)), ); // Optional: Clear the error after showing it AuthPulses.clearMessages.pulse(null); } }, child: Scaffold( body: Center( child: AirView((context) { return ElevatedButton( onPressed: () => AuthPulses.login.pulse(credentials), child: Text('Sign In'), ); }), ), ), ); }}How It Works
Section titled “How It Works”- Subscription: In
initState,AirListenersubscribes to the underlyingAirControllers associated with the keys provided in thelistenlist. - Execution: When any observed state changes, the
listenercallback is invoked safely. - No Rebuilds: The
childwidget is not rebuilt when state changes occur. It only rebuilds according to the standard Flutter widget lifecycle or if wrapped in anAirView.
Comparison
Section titled “Comparison”| Widget | Purpose | Rebuilds UI? |
|---|---|---|
AirView | To re-draw the UI based on state changes. | Yes |
AirListener | To execute one-off side-effects when state changes. | No |
Best Practices
Section titled “Best Practices”- Use for Side-effects Only: Never use
setStateinside thelistenerto update the widget’s internal UI state. If you need UI updates based on global state, useAirView. - Top-level Placement: Place
AirListenerhigh enough in the widget tree so it encompasses the scope where the side-effect (like a Navigator or ScaffoldMessengercontext) remains valid.