get_it_modular_with_auto_route 2.2.1
get_it_modular_with_auto_route: ^2.2.1 copied to clipboard
An integration for get_it_modular that simplifies modular routing by providing convenient wrappers and helpers for the auto_route package.
GetIt Modular with AutoRoute đ§©+đ #
An opinionated, contract-based framework for building scalable, modular Flutter applications. This package provides a complete architectural scaffolding using get_it for dependency injection and auto_route for navigation.
Philosophy #
This package provides an "architecture-in-a-box." It's designed for teams and projects that want a clear, consistent, and scalable structure from day one. By providing a set of abstract contracts, it ensures that your application's core componentsâdependency injection, routing, and initializationâare cleanly separated and managed.
The Core Contracts #
This framework is built upon a set of abstract classes you will implement:
ModuleContract: The blueprint for a self-contained feature. Each module defines its own dependencies and routes.ModuleSettingsContract: The central orchestrator. This is where you register all your app's feature modules.AppRouterContract: Your application's router. It automatically collects and builds the route map from all registered modules.ModularAppContract: The root of your application widget. It ties all the other contracts together and manages the app's initialization sequence.ModuleScope: AStatefulWidgetthat automatically manages the lifecycle of a module's dependencies, loading them only when a module's routes are active.
Usage #
Hydrating routes with resolvers #
Use RouteModelResolver<T> when a page needs an async model before it can render. Register the resolver inside the owning module so it participates in that module's lifecycle:
class InitializationModule extends ModuleContract {
@override
FutureOr<void> registerDependencies() {
registerRouteResolver<GreetingModel>(() => GreetingResolver());
}
}
registerRouteResolver ensures the resolver is unregistered when the module scope is disposed. Next, extend ResolverRoute<TModel, TModule> so the router automatically waits for the resolver result before building the screen. Provide any inputs via resolverParams and use the hydrated model inside buildScreen:
class InitRoute extends ResolverRoute<GreetingModel, InitializationModule> {
const InitRoute({super.key});
@override
RouteResolverParams get resolverParams => const {'name': 'Flutter'};
@override
Widget buildScreen(BuildContext context, GreetingModel model) {
return InitScreen(model: model);
}
}
ResolverRoute also exposes optional lifecycle hooks so you can tap into resolver activity without rewriting the widget:
class InitRoute extends ResolverRoute<GreetingModel, InitializationModule> {
const InitRoute({super.key})
: super(
onResolveStart: (params) => analytics.log('InitRoute:start', params),
onResolveSuccess: (model) => analytics.log('InitRoute:success'),
onResolveError: (error, _) => reportError(error),
);
}
This keeps your routes from touching repositories directlyâthe resolver handles data fetching, while the page focuses on UI. See the runnable example in example/lib/application/modules/initialization_module.dart and example/lib/presentation/init/init_route.dart for a complete setup that registers a resolver, passes params, and renders the resolved model.