Estoy usando el nuevo Dagger2 (ver 2.11) y estoy usando las nuevas características como AndroidInjector
y ContributesAndroidInjector
. Tengo un subcomponente de actividad,
@Module
abstract class ActivityBuilderModule {
@ContributesAndroidInjector(modules =
{UserListModule.class, MainFragmentModule.class})
@ActivityScope
abstract MainActivity bindsMainActivity();
}
@Module
public abstract class MainFragmentModule {
@ContributesAndroidInjector
@FragmentScope
@FragmentKey(UserListFragment.class)
abstract UserListFragment bindsUserListFragment();
}
Y el UserListModule
proporciona dependencias para el fragmento. Algunas de las dependencias solo quiero vincular las instancias y devolverlas, como
@Binds
@ActivityScope
abstract UserListView mUserListView(UserListFragment userListFragment);
En lugar de simplemente devolver la dependencia, como
@Provides
@ActivityScope
UserListView mUserListView(UserListFragment userListFragment){
return userListFragment;
}
Mi módulo contiene algunos @Provides
métodos también. ¿Podemos usar ambos? @Binds
y @Provides
métodos en el mismo módulo? Intenté como se muestra a continuación
@Module
public abstract class UserListModule {
@Provides
@ActivityScope
UserListFragment mUserListFragment() {
return new UserListFragment();
}
@Binds
@ActivityScope
abstract UserListView mUserListView(UserListFragment userListFragment);
// other provides and binds methods...
......
.....
}
Y es un error de lanzamiento
Error:(22, 8) error: dagger.internal.codegen.ComponentProcessor was unable to process this interface because not all of its dependencies could be resolved. Check for compilation errors or a circular dependency with generated code.
¿Hay alguna manera de hacer esto?
@Binds
y @ContributesAndroidInjector
los métodos deben ser abstractos, porque no tienen cuerpos de método. Eso significa que deben ir a una interfaz o clase abstracta. @Provides
los métodos pueden ser static
lo que significa que pueden utilizar clases abstractas e interfaces compiladas con Java-8, pero no estáticas (“instancia”) @Provides
los métodos no funcionan en clases abstractas. Esto se enumera explícitamente en las preguntas frecuentes de Dagger, en las secciones “¿Por qué no puedo @Binds
e instancia @Provides
métodos van en el mismo módulo?” y “¿Qué hago en su lugar?”.
Si tu @Provides
el método no usa el estado de la instancia, puede marcarlo static
y puede ir a una clase abstracta adyacente a su @Binds
métodos. Si no, considere poner los enlaces como @Binds
y @ContributesAndroidInjector
en una clase separada, posiblemente una clase anidada estática, e incluyendo eso usando el includes
atributo en Dagger’s @Module
anotación.
Una pequeña adición a la solución de Jeff anterior:
puede crear una interfaz interna en lugar de una clase interna estática, como esta:
@Module(includes = AppModule.BindsModule.class)
public class AppModule {
// usual non-static @Provides
@Provides
@Singleton
Checkout provideCheckout(Billing billing, Products products) {
return Checkout.forApplication(billing, products);
}
// interface with @Binds
@Module
public interface BindsModule {
@Binds
ISettings bindSettings(Settings settings);
}
}
-
Además de eliminar la palabra clave abstracta repetitiva, ¿hay alguna ventaja/desventaja en usar una interfaz en lugar de una clase abstracta?
– Pablo T.
6 de junio de 2019 a las 9:05
-
Además de eliminar la palabra clave abstracta repetitiva, ¿hay alguna ventaja/desventaja en usar una interfaz en lugar de una clase abstracta?
– Pablo T.
6 de junio de 2019 a las 9:07
levon petrosyan
En kotlin, puedes aprovechar objeto compañero
@Module
abstract class MyDaggerModule {
@Binds
abstract fun provideSomething(somethingImpl: SomethingImpl): Something
companion object {
@Provides
fun provideAnotherThing(): AnotherThing {
return AnotherThing()
}
}
}
-
¿No funciona con encuadernación múltiple?
– DEVS bit a bit
21 de febrero de 2022 a las 16:44
jamescodificando ahora
Esta es otra solución de tipo: agregue módulos a otro módulo después de eso, puede llamar al módulo superior en la interfaz de su componente. Puede ser más eficiente porque puede usar abstracto y estático.
Los detalles y ejemplos se encuentran a continuación:
Por ejemplo, tenemos una interfaz de componentes y dos módulos como ComponentClasses, Módulo_ClaseA y Módulo_ClaseB.
Módulo_ClaseA es:
@Module
public class Module_ClassA {
@Provides
static ClassA provideClassA(){
return new ClassA();
}
}
Módulo_ClaseB es:
@Module
abstract class Module_ClassB {
@Binds
abstract ClassB bindClassB(Fragment fragment); //Example parameter
}
Así que ahora, tenemos dos modelos. Si desea usarlos juntos, puede agregar uno de ellos al otro. Por ejemplo: puede agregar Módulo_ClaseB a Módulo_ClaseA:
@Module(includes = Module_ClassB.class)
public class Module_ClassA {
@Provides
static ClassA provideClassA(){
return new ClassA();
}
}
Finalmente, no necesita agregar ambos módulos a su clase de componente. Solo puede agregar su módulo superior en su clase de componente, así:
ComponentClasses es:
@Component(modules = Module_ClassA)
public interface ComponentClasses {
//Example code
ArrayList<CustomModel> getList();
}
Sin embargo, debe tener cuidado porque necesita agregar su módulo superior. Por lo tanto, Module_ClassA se agregó en la interfaz ComponentClasses.
Te das cuenta de que los fragmentos que agregas al administrador de fragmentos serán recreados por el sistema y probablemente no estarán en el Módulo después de la muerte del proceso, ¿verdad?
– EpicPandaForce
7 de octubre de 2017 a las 9:47
¿Querías decir que no debería Scope el fragmento? ¿Puedes ser más claro, por favor? no te entendí bien
– usuario4260260
7 de octubre de 2017 a las 9:51
Después de la muerte de un proceso, el fragmento será inicializado por el sistema y no por este módulo. Por lo tanto, es probable que termine con 2 instancias.
– EpicPandaForce
7 de octubre de 2017 a las 9:58
Está bien, pero ¿qué pasa con la pregunta real? ¿Podemos usar los métodos Binds y Provides en el mismo módulo?
– usuario4260260
7 oct 2017 a las 10:06
Creo
@Binds
+@Provides
debería funcionar, pero no sé cómoContributesAndroidInjector
lo afecta– EpicPandaForce
7 de octubre de 2017 a las 10:08