Event Dispatcher Documentation

Overview

The AppEventsDispatcher is a centralized event management system that allows you to publish and listen to app-wide events using a type-safe, stream-based pattern.

🧐 Instead of asking all your components to know each others

  • You just publish an event and all the interested parties will react accordingly.
  • You can also buffer events for late subscribers.
  • And combine it with ConditionalWidgetsEvents to show one-time widgets based on events. (ex : ask for rating, show update prompt...)

the AppEventsDispatcher is available within the

  • lib/core/states/events_dispatcher.dart file.

Why Use It?

Use the Event Dispatcher when you need to:

  • Trigger one-time events that should be shown/executed only once (ratings, reviews, updates)
  • Decouple components - emit events without knowing who listens
  • Maintain event history - late subscribers can access recent events
  • Type-safe filtering - listen only to specific event types

Ex: I send an event when user execute a task. I want all the parts that have a list of tasks to update when that happens. Instead of passing callbacks or using state management, I just publish an event and all the listeners will react accordingly.

Pattern

The dispatcher uses Dart streams with a broadcast pattern, allowing multiple listeners and maintaining a buffer of recent events for subscribers that connect after an event is published.

Basic Usage

1. Define Your Event

class MyCustomEvent extends AppEvent {
  final String message;
  MyCustomEvent(this.message);
}

2. Publish an Event

ref.publishAppEvent(MyCustomEvent("Hello!"));

3. Listen to Events

ref.onAppEvent<MyCustomEvent>().listen((event) {
  print(event.message);
});

ConditionalWidgetsEvents

This widget allows you to manage multiple events listeners in a clean way within your widget tree. The first widget that answers to an event will be displayed.

👉 So the order of the widgets matters.

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

  
  Widget build(BuildContext context, WidgetRef ref) {
    return ConditionalWidgetsEvents(
      eventWidgets: [
        // These widgets listen for specific events and show once
        MaybeAskForRating(),      // Listens to RatingRequestEvent
        MaybeAskForReview(),       // Listens to ReviewRequestEvent
        MaybeShowPremiumPage(),    // Listens to PremiumPromptEvent
        MaybeShowUpdateBottomSheet(), // Listens to UpdateAvailableEvent
        MaybeShowNotificationPermission(), // Listens to NotificationPermissionEvent
      ],
      child: YourAppContent(),
    );
  }
}

Each widget subscribes to its event type and displays when the event is published. Or they can listen multiple events if needed.

Write a maybe widget

class MaybeAskForReview implements MaybeShowWithRef {
  MaybeAskForReview();

  
  Future<bool> handle(WidgetRef ref, AppEvent event) async {
    if (event is! UserActionEvent) {
      return false;
    }
    await ref.read(ratingApiProvider).showReviewDialog();
    return true;
  }
}
  • The handle method checks if the event is of the expected type.
  • If it matches, it performs the action (e.g., showing a dialog) and returns true.
  • If it doesn't match, it returns false, allowing the next widget to handle the event.

🧐 All this code is only available once you generated an ApparenceKit app