event_ddi 0.0.1
event_ddi: ^0.0.1 copied to clipboard
A Dart package designed for event management. It provides tools to create, destroy, and listen to events.
Event DDI Package #
A Dart package designed for event management. It provides tools to create, destroy, and listen to events, making it easier to decouple different parts of your application and handle communication efficiently.
Features #
-
Event Management: Create, manage, and destroy events effortlessly.
-
Flexible Subscriptions: Support for synchronous, asynchronous, and isolate-based event subscriptions.
-
Replay and Undo: Support for event replay and undo functionalities.
-
Qualifiers: Use qualifiers to distinguish between different event types.
Packages #
- Flutter DDI - This package is designed to facilitate the dependency injection process in your Flutter application.
- Dart DDI - This package is a robust and flexible dependency injection mechanism.
Projects #
- Budgetopia - An intuitive personal finance app that helps users track expenses.
Creating and Managing Events #
The Events follow a straightforward flow. Functions or methods subscribe to specific events using the subscribe method of the DDIEvent class. Events are fired using the fire or fireWait methods, triggering the execution of all subscribed callbacks. Subscribed callbacks are then executed, handling the event data and performing any specified tasks. Subscriptions can be removed using the unsubscribe function.
Subscribing an Event #
When subscribing to an event, you have the option to choose from three different types of subscriptions:
DDIEvent.instance.subscribeIt's the common type, working as a simples callback.DDIEvent.instance.subscribeAsyncRuns the callback as a Future.DDIEvent.instance.subscribeIsolateRuns as a Isolate.
Subscribe
The common subscription type, subscribe, functions as a simple callback. It allows you to respond to events in a synchronous manner, making it suitable for most scenarios.
Obs: If you register an event that uses async and await, it Won't be possible to wait even using fireWait. For this scenario, use subscribeAsync.
Parameters:
event:The callback function to be executed when the event is fired.qualifier:Optional qualifier name to distinguish between different events of the same type.canRegister:A FutureOrcanUnsubscribe:Indicates if the event can be unsubscribe. Ignored ifautoRunis used.priority:Priority of the subscription relative to other subscriptions (lower values indicate higher priority). Ignored ifautoRunis used.unsubscribeAfterFire:If true, the subscription will be automatically removed after the first time the event is fired. Ignored ifautoRunis used.lock: Indicates if the event should be locked. Running only one event simultaneously. Cannot be used in combination withautoRun.onError: The callback function to be executed when an error occurs.onComplete: The callback function to be executed when the event is completed. It's called even if an error occurs.expirationDuration: The duration after which the subscription will be automatically removed.retryInterval: Adds the ability to automatically retry the event after the interval specified.defaultValue: The default value to be used when the event is fired. Required ifretryIntervalis used.maxRetry: The maximum number of times the subscription will be automatically fired ifretryIntervalis used.- Can be used in combination with
autoRunandonError. - If
maxRetryis 0 andautoRunis true, will run forever. - If
maxRetryis greater than 0 andautoRunis true, the subscription will be removed when the maximum number of retries is reached. - If
maxRetryis greater than 0,autoRunis false andonErroris used, the subscription will stop retrying when the maximum number is reached. - If
expirationDurationis used, the subscription will be removed when the first rule is met, either when the expiration duration is reached or when the maximum number of retries is reached.
- Can be used in combination with
autoRun: If true, the event will run automatically when the subscription is created.- Only one event is allowed.
canUnsubscribeis ignored.unsubscribeAfterFireis ignored.priorityis ignored.- Cannot be used in combination with
lock. - Requires the
defaultValueparameter. - If
maxRetryis 0, will run forever.
filter: Allows you to filter events based on their value. Only events when the filter returns true will be fired.
void myEvent(String message) {
print('Event received: $message');
}
DDIEvent.instance.subscribe<String>(
myEvent,
qualifier: 'exampleEvent',
canRegister: () => true,
canUnsubscribe: true,
priority: 0
unsubscribeAfterFire: false,
lock: false,
onError: (Object? error, StackTrace stacktrace, String valor){},
onComplete: (){},
expirationDuration: const Duration(seconds: 5),
retryInterval: const Duration(seconds: 4),
defaultValue: 'defaultValue',
maxRetry: 1,
autoRun: false,
filter: (value) => true,
);
Subscribe Async
The subscribeAsync type runs the callback as a Future, allowing for asynchronous event handling. Making it suitable for scenarios where asynchronous execution is needed without waiting for completion.
Note that it not be possible to await this type of subscription.
Obs: If you want to await for the event to be completed, fire it using fireWait.
Parameters are the same as for subscribe.
void myEvent(String message) {
print('Event received: $message');
}
DDIEvent.instance.subscribeAsync<String>(
myEvent,
qualifier: 'exampleEvent',
canRegister: () => true,
canUnsubscribe: true,
unsubscribeAfterFire: false,
lock: false,
onError: (Object? error, StackTrace stacktrace, String valor){},
onComplete: (){},
expirationDuration: const Duration(seconds: 5),
retryInterval: const Duration(seconds: 4),
defaultValue: 'defaultValue',
maxRetry: 1,
autoRun: false,
filter: (value) => true,
);
Subscribe Isolate
The subscribeIsolate type runs the callback in a separate isolate, enabling concurrent event handling. This is particularly useful for scenarios where you want to execute the event in isolation, avoiding potential interference with the main application flow.
Parameters are the same as for subscribe.
void myEvent(String message) {
print('Event received: $message');
}
DDIEvent.instance.subscribeIsolate<String>(
myEvent,
qualifier: 'exampleEvent',
canRegister: () => true,
canUnsubscribe: true,
unsubscribeAfterFire: false,
lock: false,
onError: (Object? error, StackTrace stacktrace, String valor){},
onComplete: (){},
expirationDuration: const Duration(seconds: 5),
retryInterval: const Duration(seconds: 4),
defaultValue: 'defaultValue',
maxRetry: 1,
autoRun: false,
filter: (value) => true,
);
Unsubscribing an Event #
To unsubscribe from an event, use the unsubscribe function:
DDIEvent.instance.unsubscribe<String>(
myEvent,
qualifier: 'exampleEvent',
);
Firing an Event #
To fire an event, use the fire or fireWait function. Using fireWait makes it possible to wait for all events to complete.
qualifier:Optional qualifier name to distinguish between different events of the same type.canReplay:A boolean that indicates if the value canundo. The max history allowed is 5 events.
DDIEvent.instance.fire('Hello, Dart DDI!', qualifier: 'exampleEvent', canReplay: false);
await DDIEvent.instance.fireWait('Hello, Dart DDI!', qualifier: 'exampleEvent', canReplay: true);
Undo an Event #
The undo method reverts the last fired event if it was marked with canReplay: true. The max history allowed is 5 events.
DDIEvent.instance.undo<EventType>(qualifier: 'exampleEvent');
Redo an Event #
The redo method re-executes the last undone event if it exists. This allows users to redo actions that were previously undone.
- Requires to call
undofirst. - After
fireorfireWait, theredohistory is cleared.
DDIEvent.instance.redo<EventType>(qualifier: 'exampleEvent');
Clear Event History #
The clearHistory method clears the entire history of fired events, removing the ability to undo or redo any prior events.
DDIEvent.instance.clearHistory<EventType>(qualifier: 'exampleEvent');
Get Current Value #
The getValue method retrieves the current value of the last event fired. This can be helpful for accessing the state of the last event without firing it again.`
final EventType value = DDIEvent.instance.getValue<EventType>(qualifier: 'exampleEvent');
DDIEvent Sender Mixin #
The DDIEventSender mixin was designed to simplify the process of sending events values to listeners. They provide the method fire to send the specified value to an event.
Example Usage:
class MyEvent with DDIEventSender<String> {
void businessLogic() {
fire('Hello World');
}
}
Events Considerations #
When using the Event System, consider the following:
Event Granularity: Design events with appropriate granularity to ensure they represent meaningful actions or states in the application.
Modularity: Keep events and their handlers modular and self-contained.
Single Responsibility: Ensure each event and its handler have a single responsibility.
Possible Problems: Be cautious of potential issues such as race conditions and excessive use of isolate-based event handling, which may impact performance.
Unnecessary Locking: Applying locks to events unnecessarily may hinder the application's responsiveness. Use locking only when essential to prevent conflicting event executions.
Event Looping: Carefully manage scenarios where events trigger further events, as this can lead to infinite loops or excessive event cascades.
See the considerations about Qualifiers.
Use Cases #
Application Lifecycle: Manage events related to the application's lifecycle.
Data Synchronization: Handle data synchronization events between local and remote data sources.
Background Task: Coordinate background tasks and events for efficient task execution.
Custom Event Bus: Build a custom event bus for inter-component communication, allowing different parts of the application to communicate without tight coupling.
Notifications: Implement notifications for updates in various parts of the application, such as new messages, alerts, or data changes.