¿Cómo soluciono el error de Dagger 2 '... no se puede proporcionar [...]'?
Esta es una pregunta canónica porque es un error común con Dagger 2.
Si su pregunta fue marcada como duplicada, lea esta publicación detenidamente y asegúrese de comprender qué significa este error y por qué ocurrió. Si esta publicación no funciona para usted, asegúrese de incluir dónde y cómo brinda las clases mencionadas e incluya el mensaje de error completo en su pregunta como la que se muestra aquí.
Intenté usar una dependencia con Dagger 2, pero recibo el siguiente error cuando intento compilar mi proyecto:
error: com.ejemplo. MyDependency no se puede proporcionar sin un constructor @Inject o desde un método anotado por @Provides.
com.ejemplo. MyDependency se proporciona en
com.example.MyComponent.myDependency()
¿Qué significa esto y cómo puedo solucionarlo?
Tengo un componente y traté de proporcionar una dependencia. Mi configuración básica se ve así:
// this is the dependency I try to use
class MyDependency {}
@Component
interface MyComponent {
// I want to make it accessible to be used with my component
MyDependency myDependency();
}
tl;dr Olvidó agregar un an @Inject
a su constructor para que Dagger pueda usar Constructor injection para proporcionar el objeto, o necesita algún método en uno de sus módulos que cree o vincule el objeto.
¿Qué está sucediendo?
Mire bien el mensaje de error: Indica que intenta solicitar una dependencia pero Dagger no tiene forma de proporcionarla o crearla . Simplemente no sabe cómo hacerlo, porque no se puede proporcionar sin un constructor @Inject o desde un método anotado @Provides.
Una mirada detenida al mensaje de error muestra la clase (a) que está intentando proporcionar y el componente (b) que lo necesita.
com.example.MyDependency (a) se proporciona en
com.example.MyComponent.myDependency() (b)
Debe asegurarse de que (b) pueda crear o proporcionar (a) para solucionar su problema.
Parece un poco más complejo si intentaste inyectar tu dependencia en otro lugar, pero aún puedes ver la pila completa de eventos; en este caso, a la inyección del constructor le falta una dependencia. La clase (a) que está intentando proporcionar y la ubicación (b) donde Dagger intentó inyectarla. También le indica dónde se creó esa clase dependiente (c) y nuevamente el componente (d) que falló al proporcionar (a) .
com.example.MyDependency no se puede proporcionar sin un constructor @Inject o desde un método anotado @Provides.
com.example.MyDependency (a) se inyecta en
com.example.DependentClass.(dependencia) (b)
com.example.DependentClass se proporciona en (c)
com.example.MyComponent.myDependency() (d)
Lo mismo se aplica aquí: asegúrese de que (d) sepa cómo proporcionar (a) y estará listo.
¿Cómo puedo solucionar esto?
Eche un vistazo al error que se muestra arriba. Asegúrese de comprender dónde ocurrió y qué está intentando inyectar. Luego dile a Dagger cómo proporcionar tu objeto.
un constructor @Inject
Como indica el error, intentas usarlo MyDependency
pero MyComponent
no sabes cómo hacerlo. Si echamos un vistazo al ejemplo, queda claro por qué:
class MyDependency {}
¡ La clase no tiene @Inject
constructor anotado ! Y no hay ningún otro módulo en el componente, por lo que Dagger no puede hacer nada.
Si desea utilizar la inyección de constructor, puede simplemente agregar un @Inject
constructor anotado y listo. Dagger verá este constructor y sabrá cómo crear su clase.
class MyDependency {
@Inject
MyDependency() { /**/ }
}
Eso es todo lo que tienes que hacer cuando puedas utilizar la inyección de constructor.
de un método anotado por @Provides
El mensaje de error indica una segunda opción, que le permite proporcionar un objeto si no desea (o no puede) utilizar la inyección del constructor. También puede agregar un @Provides
método anotado a un módulo y agregar este módulo a su componente.
@Module
class MyModule {
@Provides
MyDependency provideMyDependency() {
return new MyDependency();
}
}
@Component(modules = MyModule.class)
interface MyComponent {
MyDependency myDependency();
}
De esta manera, Dagger puede usar su módulo para crear y proporcionar su dependencia. Es un poco más repetitivo que usar Constructor Inyección, pero tendrás que usar Módulos para todo lo que necesite mayor configuración o que no tenga un constructor anotado, por ejemplo, bibliotecas de terceros como Retrofit, OkHttp o Gson.
También hay otras formas de proporcionar una dependencia de un componente. A @SubComponent
tiene acceso a sus dependencias principales y una dependencia de componente puede exponer algunas de sus dependencias a sus componentes dependientes. Pero en algún momento, todo lo que proporciona Dagger debe tener un @Inject
constructor o un módulo que lo proporcione.
¡Pero agregué MyDependency
!
Presta mucha atención a los detalles. Probablemente esté utilizando una interfaz cuando solo proporciona la implementación, o intente usar una clase principal cuando Dagger solo conoce la subclase.
Tal vez agregaste una costumbre @Qualifier
o usaste @Named("typeA")
con ella. ¡Para Dagger este es un objeto completamente diferente! Verifique que realmente proporcione y solicite la misma dependencia.
Lea el error y asegúrese de tener un @Inject
constructor anotado, un módulo que tenga un @Provides
método que proporcione ese tipo o un componente principal que lo haga.
¿Qué pasa si quiero proporcionar una implementación para mi interfaz?
Un ejemplo simple como el siguiente muestra cómo una clase extiende a otra:
class MyDependency extends MyBaseDependency {
@Inject MyDependency() { super(); }
}
Esto informará a Dagger sobre MyDependency
, pero no sobre MyBaseDependency
.
Si tiene una clase que implementa una interfaz o extiende una superclase, debe declararla. Si usted proporciona MyDependency
esto no significa que Dagger pueda proporcionarlo MyBaseDependency
. Puede utilizarlo @Binds
para informarle a Dagger sobre su implementación y proporcionarla cuando se requiera la superclase.
@Module
interface MyModule {
@Binds
MyBaseDependency provideMyBaseDependency(MyDependency implementation);
}