Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Injeçao de Dependencias #937

Open
julioffigueiredo opened this issue Feb 17, 2024 · 17 comments
Open

Injeçao de Dependencias #937

julioffigueiredo opened this issue Feb 17, 2024 · 17 comments
Labels
new New issue request attention question Questions about using some feature or general working of the package

Comments

@julioffigueiredo
Copy link

Tenho no meu AppModule

image

Esses 2 ultimos binds selecionados serão importados na tela de login puxados qdo importo o LoginController que está declarado no LoginModule

image

LoginController() receba a injeção de ApiAuthService() que recebe a injeção de ApiAuthRepository();

O problema é que ele parece que não olha os binds declarados no app_module

Exception has occurred.
BindNotFoundException (BindNotFoundException: UnregisteredInstance: ApiAuthService not registered.
Trace: LoginController->ApiAuthService
LoginController => ApiAuthService

Estou fazendo algo de errado ou isso é bug, como estou usando a versão 6 pela primeira vez estou com esse problema, na versão 5 sempre foi certinho assim.

Caso eu passe o bind do LoginController() do login_module pro app_module, ele acha e faz a criação das classes certinho!

@julioffigueiredo julioffigueiredo added new New issue request attention question Questions about using some feature or general working of the package labels Feb 17, 2024
@carlossulzer
Copy link

Estou com o mesmo problema. Parece que os modulos não estão sendo importados. No meu caso usei o exportedBinds e também não funcionou. Estou utilizando a versão 6.3.2 do modular

@julioffigueiredo
Copy link
Author

Estou com o mesmo problema. Parece que os modulos não estão sendo importados. No meu caso usei o exportedBinds e também não funcionou. Estou utilizando a versão 6.3.2 do modular

Carlos depois de procurar muito, e eu não sei se o que fiz está certo, mas mesmo assim postei aqui minha dúvida, pq do jeito q era antes, funcionava como uma árvore e era possível acessar tudo que fosse na linha acima.
Mas coloquei esse código no modulo de login e ele "importou?!", mas achei bem esquisito.

@override List<Module> get imports => [ AppModule(), ];

@FelCarv01
Copy link

Estou com o mesmo problema. Parece que os modulos não estão sendo importados. No meu caso usei o exportedBinds e também não funcionou. Estou utilizando a versão 6.3.2 do modular

Carlos depois de procurar muito, e eu não sei se o que fiz está certo, mas mesmo assim postei aqui minha dúvida, pq do jeito q era antes, funcionava como uma árvore e era possível acessar tudo que fosse na linha acima. Mas coloquei esse código no modulo de login e ele "importou?!", mas achei bem esquisito.

@override List<Module> get imports => [ AppModule(), ];

Julio está correto como você usou
class XptoModule extends Module { @override void exportedBinds(i) { // Dependencies } }
e onde quiseres usar as dependências
class AbcModule extends Module { @override List<Module> get imports => [XptoModule()]; }

@julioffigueiredo
Copy link
Author

julioffigueiredo commented Feb 20, 2024

Continuando a fazer testes aqui, eu acho que a função i.addSingleton()/Lazy está com algum tipo de bug, está sendo recriada.
Seguindo a criação com os passos acima e disponibilizando um instancia de AppInfoStore, na AppModule via i.addSingleton(), e depois a importando na LoginModule via import, a cada criação eu printo um UUID que gero no construtor.

Não sei pq ele a cria 2 vezes e printa o seguinte:
[log] ID criando o AppInfoStore: ac7a783f-fe40-490b-975d-84008f4b7c97
[log] ID criando o AppInfoStore: b2c465f3-bd50-49b5-8a2a-c1984ed8b9ea

Caso eu faça o Module.get() em units separadas ele me retorna
[log] Id da instância do AppInfoStore na LoginController : b2c465f3-bd50-49b5-8a2a-c1984ed8b9ea
[log] Id da instância do AppInfoStore na LoginPage ac7a783f-fe40-490b-975d-84008f4b7c97
Não sei como e pq ele pega uma instância diferente em cada unit

@carlossulzer
Copy link

No meu caso o problema estava no uso do SharedPreference com o modular. O flutter_modular não aceita bind assíncrono. Segue o código que funcionou para mim.

void main() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();

runApp(ModularApp(
module: AppModule(sharedPreferences: sharedPreferences),
child: const AppWidget(),
));
}

class AppModule extends Module {
final SharedPreferences sharedPreferences;

AppModule({
required this.sharedPreferences,
});

@OverRide
List get imports => [
CoreModule(sharedPreferences: sharedPreferences),
AuthModule(),
];

@OverRide
void routes(RouteManager r) {
r.module('/auth', module: AuthModule());
}
}


class CoreModule extends Module {
final SharedPreferences sharedPreferences;
CoreModule({
required this.sharedPreferences,
});

@OverRide
void exportedBinds(Injector i) {
i.addLazySingleton((i) => LoginController());

i.addInstance<LocalStorage>(
  SharedPreferencesStorageImpl(instanceSharedPreference: sharedPreferences),
);
i.addSingleton<AuthStore>(AuthStore.new);

}
}

@jeffdgr8
Copy link

jeffdgr8 commented Mar 9, 2024

I experienced this same issue after upgrading from 5.0.3 to 6.3.2 and migrating to the new auto_injector API. At first I thought the same thing, that the AppModule dependencies weren't visible to the LoginModule, but after further testing, I discovered if I change the syntax from using the constructor function reference:

i.addLazySingleton(LoginController.new);

to calling the constructor explicitly in a lambda:

i.addLazySingleton(() => LoginController(i()));

then it works.

This seems to only be a problem when using a constructor function reference that requires a dependency from a different module. Using a constructor function reference seems to work as long as all its parameters are dependencies in the same module.

@ktnishide
Copy link

Modular 6.3.3
same here.
when using .new , BindNotFoundException happens.
if changed on child module to "lambda" it works

I experienced this same issue after upgrading from 5.0.3 to 6.3.2 and migrating to the new auto_injector API. At first I thought the same thing, that the AppModule dependencies weren't visible to the LoginModule, but after further testing, I discovered if I change the syntax from using the constructor function reference:

i.addLazySingleton(LoginController.new);

to calling the constructor explicitly in a lambda:

i.addLazySingleton(() => LoginController(i()));

then it works.

This seems to only be a problem when using a constructor function reference that requires a dependency from a different module. Using a constructor function reference seems to work as long as all its parameters are dependencies in the same module.

@ktnishide
Copy link

ktnishide commented Apr 16, 2024

if I import all parent modules in the child module, it also works but doesn't seem to be aligned with what we see on Modular 5...
However, other frameworks use this approach(importing all dependencies and not inheriting) such as Angular, Vue, etc...
are you doing the same?

what are the guidelines?
could you please document it since it is a breaking of paradigm from Modular 5 to 6.

importing parent modules:

class FeedModule extends Module {
  @override
  List<Module> get imports => [GlobalModule(), AppModule(), MenuModule()];

  @override
  void binds(i) {
    i.addSingleton<FeedStore>(FeedStore.new);
  }
...

using lambda syntax:

class FeedModule extends Module {
  @override
  void binds(i) {
    i.addSingleton<FeedStore>(() => FeedStore(i(), i(), i()));
  }
...

@bielCostta
Copy link

I had a similar problem.
was reporting to me that my injections were not being found. After many tests it worked for me to change from:

i.add((i) => environment);

to:

i.add(() => environment);

I thought it was strange, but it worked.
flutter_modular version: 6.3.4

@jeffdgr8
Copy link

jeffdgr8 commented Jun 1, 2024

Version 6.3.4 seems to have now made this bug worse. Now even the

i.addLazySingleton(() => LoginController(i()));

syntax fails to find dependencies declared in a separate module.

The bug is actually in the modular_core version 3.3.3 dependency.

@intellitour
Copy link

Yep... same bug here. Anyone has find a workaround/fix for this?
@jacobaraujo7 we need some help on this

@eduardoflorence
Copy link

Please, we need a minimum code to be placed here so that we can check the error (main + module + widgets).
I can say that I work with version 6.3.4 and everything works normally

@intellitour
Copy link

I am available to book a call and demo the problem. Can't handle the code, though.

@SamuelGadiel
Copy link

Same problem here

@julioffigueiredo
Copy link
Author

Segue um projeto demonstrando o problema.

Crio uma instância de cliente e endereço no app_module, o cliente recebe de injeção o endereço.

Normalmente eles são lidos dentro da tela Home.

Na Store, caso eu queira a classe Cliente via injeção ele me retorna o erro abaixo:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: UnregisteredInstance: Cliente not registered.
HomeStore => Cliente

Se eu puxar dentro da Store a classe via Modular.get(), a dependência é encontrada!

Então acho que há algum problema ao encontrar a dependência qdo ela vem por DI.

https://github.com/julioffigueiredo/modular_import.git

@edugemini
Copy link
Contributor

Olá @julioffigueiredo,

Olhei seu exemplo e esse não é o modo correto de trabalhar com injeção de dependências compartilhadas no Modular 6.x.x.
Se você precisa compartilhar dependências, elas precisam ser declaradas num módulo à parte, por exemplo CoreModule, em exportedBinds:

class CoreModule extends Module {
  @override
  void exportedBinds(Injector i) {
    i.addSingleton<Endereco>(Endereco.new);
    i.addSingleton<Cliente>(Cliente.new);
  }
}

Depois você pode importar em qualquer módulo que precise dessas dependências, como o seu AppModule e HomeModule (em ambos terá que fazer a importação). Exemplo em HomeModule:

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

  // Aqui é só um exemplo para o caso de você precisar do bind que tem em CoreModule
  // para ser usado em outro bind da HomeModule. Neste exemplo, suponha que 
  // OutraClasse peça em seu construtor a instância de Cliente, então bastará fazer o código 
  // abaixo que ele conseguirá achar a instância de Cliente, pois foi importada de CoreModule
  @override
  void binds(i) {
    i.addSingleton(OutraClasse.new);
  }
}

Nas versões anteriores (<= 5.x.x) você precisava somente importar em AppModule e ele passava para os módulos abaixo, mas isso causava problema colaterais, então foi decidido por mudar a abordagem na versão 6.x.x

@julioffigueiredo
Copy link
Author

julioffigueiredo commented Aug 1, 2024

@edugemini,

Eu conheço como usar o "core module", estou usando assim. Mas pq dentro do mesmo nível, por exemplo, no HomeStore, eu consigo importar via Modular.get() mas não consigo importar via DI?
Se não pode/deve importar, não deveria importar por nenhum dos 2 modos.
Pra mim isso é um bug um tanto quanto estranho! Já que eu mantenho o acesso sem ser via DI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new New issue request attention question Questions about using some feature or general working of the package
Projects
None yet
Development

No branches or pull requests

10 participants