mcquenji_core library

McQuenji's Core Module

This is the core module for all my flutter projects. It contains all the basic functionalities that I use in all my projects. It is a work in progress and I will keep updating it as I go along.

Usage

To use this module in your project, add the following to your pubspec.yaml file:

dependencies:
  mcquenji_core:
    git:
      url: https://github.com/mcquenji/mcquenji_core.git

Then run flutter pub get to install the package.

After that, import the module in your app's main module this:

import 'package:mcquenji_core/mcquenji_core.dart';

class AppModule extends Module {
    @override
    List<Module> get imports => [CoreModule()];
}

Now you can use all services and utilities provided by the module in your app.

final networkService = Modular.get<NetworkService>();

networkService.get('https://api.example.com').then((response) {
    print(response.body);
});

Logging

All enteties (i.e. services, datasources, repositories) have a logger that can be used to log messages. The logger is a Logger instance from the logging package. The logger is named after the entity's runtime type.

To process the logs you can either use the LogHandlerService or create your own log handler.

void main() {
   // Call this AFTER modular is initialized
   final handler = Modular.get<LogHandlerService>();
   Logger.root.onRecord.listen(handler);
}

## Services

Services are classes that complete the most low-level tasks in the app. They are the only classes that can interact with the outside world. All other classes should depend on services to get their work done.

### Defining a new service

To define a new service, create a new abstract class that extends the `Service` class.

```dart
abstract class MyService extends Service {
    @override
    String get name => 'MyService';

    // Your service implementation here
}

After that, create a new class that extends the abstract class and implements the required methods.

class MyServiceImpl extends MyService {
    @override
    Future<void> init() async {
        // Initialize your service here
    }

    // Implement other methods here
}

Finally, register the service in the module the service is used in. If the service is also used in other modules, export it.

class MyModule extends Module {
    @override
    List<Module> get imports => [McQuenjiCore()];

    @override
    void binds(i){
        i.add<MyService>(MyServiceImpl.new);
    }

    @override
    exportBinds(i) {
        i.add<MyService>(MyServiceImpl.new);
    }
}

Datasources

Datasources are classes that interact with the data layer of the app. They are responsible for fetching and storing data from and to the data layer.

Defining a new datasource

To define a new datasource, create a new abstract class that extends the Datasource class.

abstract class MyDatasource extends Datasource {
    @override
    String get name => 'MyDatasource';

    MyDatasource(MyService service);

    // Your datasource implementation here
}

After that, the steps are the same as defining a new service.

Repositories

Repositories are classes that provide tailored methods for a specific UI screen or feature. They are also responsible for state management and as extend Cubit.

Defining a new repository

To define a new repository, create a new class that extends the Repository class.

class MyRepository<MyState> extends Repository<MyState> {
    MyRepository(MyService service, MyDatasource datasource) : super(myIntialState);

    // Your repository implementation here
}

Classes

AsyncValue<T>
Represents a value that is asynchronously loaded.
ConnectivityService
Service for checking the connectivity of the device.
CoreModule
Core module of all McQuenji projects.
Datasource
Base class for all datasources.
HttpResponse<T>
A response received from an HTTP request made by a NetworkService.
IGenericSerializer<Deserialized, Serialized>
A versatile serializer interface for converting objects between different formats.
ILoggable
A class that provides logging functionality.
InitialBuildTrigger
Passed as trigger in Repository.build when called the first time.
LogHandlerService
A service that handles logging.
NetworkService
Base class for all network services.
Repository<State>
Base class for all repositories.
Service
Base class for all services.
Tick
A tick emitted by the TickRepository.
TickInterval
An interval at which TickRepository should emit ticks.
TickRepository
A repository that emits ticks at a specified interval. The emitted ticks can be used to trigger periodic updates in the application.
UpdateTrigger
Passed as trigger in Repository.build when called in the Repository.updateInterval.

Extensions

AsyncRepoExt on Repository<AsyncValue<State>>
Utility extension on repositories with an asynchronous state.
LogRecordX on LogRecord
Formatting extension for log records.
RepositoryInjectorExt on Injector
Utility extension on Injector.
RepoWatchExt on Repository<AsyncValue<State>>
Extension for watching asynchronous repositories in asynchronous repositories.
StringX on String
String utilities.

Functions

cubitConfig<T extends Cubit>() BindConfig<T>
This function is to be used when binding a Cubit to a Module.
repositoryConfig<R extends Repository>() BindConfig<R>
This function is to be used when binding a Repository to a Module. Use RepositoryInjectorExt.addRepository instead of manually calling this function.

Typedefs

JSON = Map<String, dynamic>
Type alias for a JSON object.
Ticks = TickRepository
Type alias for TickRepository.

Exceptions / Errors

OfflineException
Exception thrown when the device is offline.
WaitForDataException
Thrown when RepoWatchExt.waitForData is called on a repository that does not have data yet.