Skip to content

Commit

Permalink
Doc: Some improvements (#5)
Browse files Browse the repository at this point in the history
- Removed Flutter related test packages
- Package structure
- Refactor Exception Handling
  • Loading branch information
Willian199 authored Jan 23, 2024
1 parent 938b319 commit 150c329
Show file tree
Hide file tree
Showing 34 changed files with 680 additions and 460 deletions.
69 changes: 59 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,17 @@ Summary
3. [Interceptor](#interceptor)
4. [RegisterIf](#registerif)
5. [Destroyable](#destroyable)
5. [Events](#events)
5. [Mixins](#mixins)
1. [Post Construct](#post-construct-mixin)
2. [Pre Destroy](#pre-destroy-mixin)
6. [Events](#events)
1. [Creating and Managing Events](#creating-and-managing-events)
2. [Subscribing an Event](#subscribing-an-event)
3. [Unsubscribing an Event](#unsubscribing-an-event)
4. [Firing an Event](#firing-an-event)
5. [Events Considerations](#events-considerations)
6. [Use Cases](#use-cases)
6. [API Reference](#api-reference)
7. [API Reference](#api-reference)
1. [registerSingleton](#registersingleton)
2. [registerApplication](#registerapplication)
3. [registerDependent](#registerdependent)
Expand Down Expand Up @@ -384,33 +387,79 @@ Designed for flexibility and efficiency, this system empowers you to seamlessly
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` method, 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
To subscribe to an event, use the `subscribe` function:
When subscribing to an event, you have the option to choose from three different types of subscriptions: `subscribe`, `subscribeAsync` and `subscribeIsolate`.

**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.

- `DDIEvent.instance.subscribe` It's the common type, working as a simples callback.
- `DDIEvent.instance.subscribeAsync` Runs as a Future. Perhaps it's not possible to await.
- `DDIEvent.instance.subscribeIsolate` Runs as a Isolate.

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.
- `registerIf:` A bool function that if returns true, allows the subscription to proceed.
- `allowUnsubscribe:` Indicates if the event can be unsubscribe.
- `priority:` Priority of the subscription relative to other subscriptions (lower values indicate higher priority).
- `isAsync:` If true, the callback function will be executed asynchronously.
- `unsubscribeAfterFire:` If true, the subscription will be automatically removed after the first time the event is fired.
- `runAsIsolate:` If true, the subscription callback will be executed in a separate isolate for concurrent event handling.

```dart
void myEvent(String message) {
print('Event received: $message');
};
}
DDIEvent.instance.subscribe<String>(
myEvent,
qualifier: 'exampleEvent',
priority: 1,
isAsync: true,
registerIf: () => true,
allowUnsubscribe: true,
unsubscribeAfterFire: false,
runAsIsolate: false,
);
```

**subscribeAsync**
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.

Parameters are the same as for `subscribe`.

```dart
void myEvent(String message) {
print('Event received: $message');
}
DDIEvent.instance.subscribeAsync<String>(
myEvent,
qualifier: 'exampleEvent',
registerIf: () => true,
allowUnsubscribe: true,
unsubscribeAfterFire: false,
runAsIsolate: true,
runAsIsolate: false,
);
```

**subscribeIsolate**
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`.

```dart
void myEvent(String message) {
print('Event received: $message');
}
DDIEvent.instance.subscribeIsolate<String>(
myEvent,
qualifier: 'exampleEvent',
registerIf: () => true,
allowUnsubscribe: true,
unsubscribeAfterFire: false,
runAsIsolate: false,
);
### Unsubscribing an Event
To unsubscribe from an event, use the `unsubscribe` function:
Expand Down
2 changes: 1 addition & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
include: package:lints/recommended.yaml

analyzer:
exclude: [build/**]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
abstract class CubitListener<State, Listen extends Object>
extends Cubit<State> {
CubitListener({required State initialState}) : super(initialState) {
DDIEvent.instance.subscribe<Listen>(onEvent, isAsync: true);
DDIEvent.instance.subscribeAsync<Listen>(onEvent);
}

void onEvent(Listen listen);
Expand Down
9 changes: 4 additions & 5 deletions example/lib/common/cubit_features/cubit_event_sender.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import 'package:flutter_bloc/flutter_bloc.dart';
class CubitSender<State extends Object> extends Cubit<State> {
CubitSender(super.initialState);

@override
void emit(State state, {bool suppresListener = false}) {
void fire(State state) {
debugPrint('emitindo evento $this');
if (!suppresListener) {
DDIEvent.instance.fire<State>(state);
}

DDIEvent.instance.fire<State>(state);

super.emit(state);
}
}
35 changes: 31 additions & 4 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,45 @@
import 'dart:async';
import 'dart:io';

import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:dio_cache_interceptor_objectbox_store/dio_cache_interceptor_objectbox_store.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart' as pp;
import 'package:perfumei/common/constants/injection_constants.dart';
import 'package:perfumei/config/services/injection.dart';
import 'package:perfumei/config/theme/dark.dart';
import 'package:perfumei/config/theme/light.dart';
import 'package:perfumei/modules/home/cubit/home_cubit.dart';
import 'package:perfumei/modules/home/view/home_page.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import 'package:perfumei/modules/item/cubit/imagem_cubit.dart';
import 'package:perfumei/modules/item/cubit/item_cubit.dart';
import 'package:perfumei/modules/item/cubit/perfume_cubit.dart';

void main() {
WidgetsFlutterBinding.ensureInitialized();

unawaited(WakelockPlus.enable());
//unawaited(WakelockPlus.enable());

Injection.start();
//Injection.start();

ddi.registerObject<String>('https://fgvi612dfz-dsn.algolia.net',
qualifier: InjectionConstants.url);

ddi.registerSingleton<GlobalKey<NavigatorState>>(
() => GlobalKey<NavigatorState>());

ddi.registerObject<bool>(
WidgetsBinding.instance.platformDispatcher.platformBrightness ==
Brightness.dark,
qualifier: InjectionConstants.darkMode);

ddi.registerDependent<HomeCubit>(() => HomeCubit());
ddi.registerDependent<TabCubit>(() => TabCubit());
ddi.registerDependent<PerfumeCubit>(() => PerfumeCubit());
ddi.registerDependent<ImagemCubit>(() => ImagemCubit());

pp.getTemporaryDirectory().then((Directory dir) =>
ddi.registerSingleton<CacheStore>(
() => ObjectBoxCacheStore(storePath: dir.path)));

runApp(const MyApp());
}
Expand Down
4 changes: 2 additions & 2 deletions example/lib/modules/item/cubit/perfume_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ class PerfumeCubit extends CubitSender<PerfumeState> {
final DadosPerfume perfume =
await compute(HtmlDecodePage.decode, retorno.data.toString());

emit(state.copyWith(dadosPerfume: perfume), suppresListener: true);
emit(state.copyWith(dadosPerfume: perfume));
}

void pageChange(int value) {
emit(state.copyWith(page: value));
fire(state.copyWith(page: value));
}
}
4 changes: 2 additions & 2 deletions lib/dart_ddi.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
library dart_ddi;

export 'src/core/dart_ddi.dart' show DDI;
export 'src/core/bean/dart_ddi.dart' show DDI;
export 'src/core/event/dart_ddi_event.dart' show DDIEvent;
export 'src/features/ddi_interceptor.dart';
export 'src/core/dart_ddi_event.dart' show DDIEvent;
export 'src/features/post_construct.dart';
export 'src/features/pre_destroy.dart';
68 changes: 36 additions & 32 deletions lib/src/core/dart_ddi.dart → lib/src/core/bean/dart_ddi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import 'dart:async';

import 'package:dart_ddi/src/data/factory_clazz.dart';
import 'package:dart_ddi/src/enum/scopes.dart';
import 'package:dart_ddi/src/exception/bean_not_found.dart';
import 'package:dart_ddi/src/exception/circular_detection.dart';
import 'package:dart_ddi/src/exception/duplicated_bean.dart';
import 'package:dart_ddi/src/features/ddi_interceptor.dart';
import 'package:dart_ddi/src/features/post_construct.dart';
import 'package:dart_ddi/src/features/pre_destroy.dart';
Expand Down Expand Up @@ -32,12 +35,12 @@ abstract class DDI {
/// **Use Case:**
/// - Suitable for objects that are stateless or have shared state across the entire application.
/// - Examples include utility classes, configuration objects, or services that maintain global state.
void registerSingleton<T extends Object>(
T Function() clazzRegister, {
void registerSingleton<BeanT extends Object>(
BeanT Function() clazzRegister, {
Object? qualifier,
void Function()? postConstruct,
List<T Function(T)>? decorators,
List<DDIInterceptor<T> Function()>? interceptors,
List<BeanT Function(BeanT)>? decorators,
List<DDIInterceptor<BeanT> Function()>? interceptors,
bool Function()? registerIf,
bool destroyable = true,
});
Expand All @@ -60,12 +63,12 @@ abstract class DDI {
/// **Use Case:**
/// - Appropriate for objects that need to persist during the entire application's lifecycle, but may have a more dynamic nature than Singleton instances.
/// - Examples include managers, controllers, or services that should persist but might be recreated under certain circumstances.
void registerApplication<T extends Object>(
T Function() clazzRegister, {
void registerApplication<BeanT extends Object>(
BeanT Function() clazzRegister, {
Object? qualifier,
void Function()? postConstruct,
List<T Function(T)>? decorators,
List<DDIInterceptor<T> Function()>? interceptors,
List<BeanT Function(BeanT)>? decorators,
List<DDIInterceptor<BeanT> Function()>? interceptors,
bool Function()? registerIf,
bool destroyable = true,
});
Expand All @@ -88,12 +91,12 @@ abstract class DDI {
/// **Use Case:**
/// - Appropriate for objects that need to persist during the entire application's lifecycle, but may have a more dynamic nature than Singleton instances.
/// - Examples include managing user authentication state or caching user-specific preferences.
void registerSession<T extends Object>(
T Function() clazzRegister, {
void registerSession<BeanT extends Object>(
BeanT Function() clazzRegister, {
Object? qualifier,
void Function()? postConstruct,
List<T Function(T)>? decorators,
List<DDIInterceptor<T> Function()>? interceptors,
List<BeanT Function(BeanT)>? decorators,
List<DDIInterceptor<BeanT> Function()>? interceptors,
bool Function()? registerIf,
bool destroyable = true,
});
Expand All @@ -115,12 +118,12 @@ abstract class DDI {
/// **Use Case:**
/// - Suitable for objects with a short lifecycle or those that need to be recreated frequently, ensuring isolation between different parts of the application.
/// - Examples include transient objects, temporary data holders, or components with a short lifespan.
void registerDependent<T extends Object>(
T Function() clazzRegister, {
void registerDependent<BeanT extends Object>(
BeanT Function() clazzRegister, {
Object? qualifier,
void Function()? postConstruct,
List<T Function(T)>? decorators,
List<DDIInterceptor<T> Function()>? interceptors,
List<BeanT Function(BeanT)>? decorators,
List<DDIInterceptor<BeanT> Function()>? interceptors,
bool Function()? registerIf,
bool destroyable = true,
});
Expand All @@ -143,60 +146,61 @@ abstract class DDI {
/// **Use Case:**
/// - Suitable for objects that are stateless or have shared state across the entire application.
/// - Examples include application or device properties, like platform or dark mode.
void registerObject<T extends Object>(
T register, {
void registerObject<BeanT extends Object>(
BeanT register, {
Object? qualifier,
void Function()? postConstruct,
List<T Function(T)>? decorators,
List<DDIInterceptor<T> Function()>? interceptors,
List<BeanT Function(BeanT)>? decorators,
List<DDIInterceptor<BeanT> Function()>? interceptors,
bool Function()? registerIf,
bool destroyable = true,
});

/// Gets an instance of the registered class in [DDI].
///
/// - `qualifier`: Optional qualifier name to distinguish between different instances of the same type.
T get<T extends Object>({Object? qualifier});
BeanT get<BeanT extends Object>({Object? qualifier});

/// Retrieves a list of keys associated with objects of a specific type `T`.
///
/// This method allows you to obtain all keys (qualifier names) that have been used to register objects of the specified type `T`.
List<Object> getByType<T extends Object>();
List<Object> getByType<BeanT extends Object>();

/// Gets an instance of the registered class in [DDI].
///
/// - `qualifier`: Optional qualifier name to distinguish between different instances of the same type.
T call<T extends Object>();
BeanT call<BeanT extends Object>();

/// Removes the instance of the registered class in [DDI].
///
/// - `qualifier`: Optional qualifier name to distinguish between different instances of the same type.
void destroy<T extends Object>({Object? qualifier});
void destroy<BeanT extends Object>({Object? qualifier});

/// Removes all the instance registered as Session Scope.
void destroyAllSession();

/// Removes all the instance registered as type `T`.
void destroyByType<T extends Object>();
void destroyByType<BeanT extends Object>();

/// Disposes of the instance of the registered class in [DDI].
///
/// - `qualifier`: Optional qualifier name to distinguish between different instances of the same type.
void dispose<T>({Object? qualifier});
void dispose<BeanT>({Object? qualifier});

/// Disposes all the instance registered as Session Scope.
void disposeAllSession();

/// Disposes all the instance registered as type `T`.
void disposeByType<T extends Object>();
void disposeByType<BeanT extends Object>();

/// Allows to dynamically add a Decorators.
///
/// When using this method, consider the following:
///
/// - **Order of Execution:** Decorators are applied in the order they are provided.
/// - **Instaces Already Gets:** No changes any Instances that have been get.
void addDecorator<T extends Object>(List<T Function(T)> decorators,
void addDecorator<BeanT extends Object>(
List<BeanT Function(BeanT)> decorators,
{Object? qualifier});

/// Allows to dynamically add a Interceptor.
Expand All @@ -207,17 +211,17 @@ abstract class DDI {
/// - **Around Constructor:** Will not work with Singletons Scope.
/// - **Order of Execution:** Interceptor are applied in the order they are provided.
/// - **Instaces Already Gets:** No changes any Instances that have been get.
void addInterceptor<T extends Object>(
List<DDIInterceptor<T> Function()> interceptors,
void addInterceptor<BeanT extends Object>(
List<DDIInterceptor<BeanT> Function()> interceptors,
{Object? qualifier});

/// Allows to dynamically refresh the Object.
///
/// When using this method, consider the following:
///
/// - **Instaces Already Gets:** No changes any Instances that have been get.
void refreshObject<T extends Object>(
T register, {
void refreshObject<BeanT extends Object>(
BeanT register, {
Object? qualifier,
});
}
Loading

0 comments on commit 150c329

Please sign in to comment.