modular
modular copied to clipboard
Migração de Modular v5 para v6
Tenho o seguinte código, como poderia migrar para a v6?
Tenho LoginModule que está dentro de app/modules/login
class LoginModule extends Module {
@override
final List<Bind> binds = [
Bind.lazySingleton((i) => LoginController(
i<IUsuarioService>(),
i<IConfiguracaoAppService>(),
i.get<LoginRepository>(),
i.get<UsuarioModel>(),
),
),
Bind.lazySingleton((i) => LoginRepository()),
Bind.lazySingleton((i) => UsuarioModel())
];
@override
final List<ModularRoute> routes = [
ChildRoute(Modular.initialRoute, child: (_, args) => const LoginPage()),
];
}
Tenho AppModule que contém todos os módulos
@override
final List<ModularRoute> routes = [
ModuleRoute(Modular.initialRoute, module: SplashModule()),
ModuleRoute('/login', module: LoginModule()),
];
Olá @adrinebt,
Veja essa parte da documentação com a comparação: https://modular.flutterando.com.br/docs/flutter_modular/migration-5-to-6
Minha dúvida é sobre como lidar com o caso do construtor de LoginController que tem as dependências IUsuarioService, IConfiguracaoAppService como funcionaria na migração não encontrei nada parecido na documentação
@override
final List<Bind> binds = [
Bind.lazySingleton((i) => LoginController(
i.get<IUsuarioService>(),
i.get<IConfiguracaoAppService>(),
i.get<LoginRepository>(),
i.get<UsuarioModel>(),
),
),
Bind.lazySingleton((i) => LoginRepository()),
Bind.lazySingleton((i) => UsuarioModel())
];
IUsuarioService
e IConfiguracaoAppService
estão no binds
de outro Módulo? Se sim, pode mostrar o nome desse outro módulo e a parte do binds dele para eu te dar um exemplo correto?
Outro exemplo é no módulo do Splash que vem antes do login que mostrei anteriormente
class SplashModule extends Module {
@override
final List<Bind> binds = [
Bind.lazySingleton((i) => SplashController()),
Bind.lazySingleton((i) => LoginController(
i.get<IUsuarioService>(),
i.get<IConfiguracaoAppService>(),
i.get<LoginRepository>(),
i.get<UsuarioModel>(),
),
),
];
@override
final List<ModularRoute> routes = [
ChildRoute(Modular.initialRoute, child: (_, args) => const SplashPage()),
];
}
Para te dar o exemplo na versão 6 corretamente, eu precisaria saber onde são declaradas as dependências IUsuarioService
e IConfiguracaoAppService
. Elas estão no binds
seu AppModule
ou num SharedModule
? Ou elas estão no binds
do LoginModule
e SplashModule
, só que você cortou ao colocar o código nos exemplos acima?
Ou seja, no LoginModule
e SplashModule
, que mostrou acima, você obtém essas dependências (IUsuarioService
e IConfiguracaoAppService
), mas em algum módulo anterior você colocou essas dependências no binds
para serem usadas posteriormente.
IUsuarioService e IConfiguracaoAppService são dependências de LoginController e declaradas em LoginModule. este por sua vez é declarado no AppModule como no código abaixo
@override
final List<ModularRoute> routes = [
ModuleRoute(Modular.initialRoute, module: SplashModule()),
ModuleRoute(routeLogin, module: LoginModule()),
ModuleRoute(routeHome, module: HomeModule()),
ModuleRoute(routeConsulta, module: ConsultaModule()),
];
Ok, acredito que não tenha você não compreendeu a informação que preciso, mas vou te dar um exemplo de como eu faria na versão 6 do Modular:
- Como
IUsuarioService
eIConfiguracaoAppService
serão usados em mais de um módulo, o ideal é colocá-los num módulo à parte com exportação. Vou supor queIUsuarioService
eIConfiguracaoAppService
são interfaces eUsuarioServiceImpl
eConfiguracaoAppServiceImpl
são as implementações destas interfaces. Faça umCoreModule
desta forma:
class CoreModule extends Module {
@override
void exportedBinds(Injector i) {
i.addSingleton<IUsuarioService>(UsuarioServiceImpl.new);
i.addSingleton<IConfiguracaoAppService>(ConfiguracaoAppServiceImpl.new);
}
}
- Seu
LoginModule
, importaráCoreModule
e ficará então desta forma:
class LoginModule extends Module {
@override
List<Module> get imports => [CoreModule()];
@override
void binds(Injector i) {
i.addLazySingleton(LoginController.new),
i.addLazySingleton(LoginRepository.new),
i.addLazySingleton(UsuarioModel.new)
}
@override
void routes(RouteManager r) {
r.child(Modular.initialRoute, child: (context) => const LoginPage()),
}
}
Ao fazer LoginController.new
o sistema de injeção de dependências fará a injeção automática de cada dependência que LoginController
precisa via construtor, basta que exista um bind dessas dependências, que foi o que fiz nos exemplos acima.
Perdão, não sei se essa era a sua dúvida agora creio que compreendi. IUSuarioService e IConfiguracaoAppService são de fato interfaces implementadas respectivamente em UsuarioService e ConfiguracaoAppService que como no código abaixo estão declaradas nos binds do AppModule
@override
final List<Bind> binds = [
Bind.lazySingleton((i) => ConfiguracaoAppService()),
Bind.lazySingleton((i) => UsuarioService(i<IUsuarioRepository>())),
Bind.lazySingleton((i) => CustomDio(i<BaseOptions>())),
Bind(
(i) => BaseOptions(
baseUrl: baseUrlNova,
contentType: Headers.formUrlEncodedContentType,
connectTimeout: const Duration(seconds: 90),
receiveTimeout: const Duration(seconds: 90),
sendTimeout: const Duration(seconds: 90),
receiveDataWhenStatusError: true,
),
),
];
Isso mesmo que eu estava querendo saber. Esse Bind que mostrou agora por último ficará assim:
class CoreModule extends Module {
@override
void exportedBinds(Injector i) {
i.addLazySingleton<IConfiguracaoAppService>(ConfiguracaoAppService.new);
i.addLazySingleton<IUsuarioService>(UsuarioService.new);
i.addLazySingleton<CustomDio>(CustomDio.new),
i.addInstance<BaseOptions>(
() => BaseOptions(
baseUrl: baseUrlNova,
contentType: Headers.formUrlEncodedContentType,
connectTimeout: const Duration(seconds: 90),
receiveTimeout: const Duration(seconds: 90),
sendTimeout: const Duration(seconds: 90),
receiveDataWhenStatusError: true,
),
),
}
}
Em cada módulo que precisar do IConfiguracaoAppService
e IUsuarioService
, você precisará importar este CoreModule como mostrei no exemplo anterior em LoginModule. Essa é a orientação no Modular 6 (No 5 não precisava)
Obs.: Não use o AppModule para fazer esse exportedBinds das dependências que serão compartilhadas, use um módulo em separado (orientação para modular 6) como o CoreModule do meu exemplo. Se até o AppModule precisar das dependências, pode importar também.
Interessante, não fiz a migração por conta disso, não havia entendido.
nesse caso o AppModule serviria somente para declarar os modules como SplashModule, LoginModule?
nesse caso o AppModule serviria somente para declarar os modules como SplashModule, LoginModule?
Sim, você até pode colocar bind nele, mas seria só de dependências que seriam usadas exclusivamente no AppModule, caso ele tivesse uma página inicial, antes de ir para outro módulo, por exemplo.
Obs.: Você consegue acessar um bind do AppModule em qualquer outro módulo declarado por ele, fazendo Modular.get<SuaDependencia>()
, mas isso não é aconselhável, pois "estraga" a sua arquitetura, já que seria por fora da injeção de dependências.