I'm playing with Dagger-2 to figure how to integrate it in our existing application and I'm facing something which I can't understand or I'm doing wrong.
My situation :
3 API without any annotated constructor ( each one in its own file )
public class DbApi { public void doSomething(String username, String password) { } } public class RestApi { public void doSomething(String username, String password) { } } public class SocketApi { public void doSomething(String username, String password) { } }
3 Modules ( each one in its own file )
@Module public class DbModule { @Provides @Singleton public DbApi getDbApi(){ return new DbApi(); } } @Module public class RestModule { @Provides @Singleton public RestApi getRestApi(){ return new RestApi(); } } @Module public class SocketModule { @Provides @Singleton public SocketApi getSocketApi(){ return new SocketApi(); } }
2 Components ( each one in its own file )
@Singleton @Component(modules = {DbModule.class}) public interface DbComponent { void inject(SecondActivity activity); } @Singleton @Component(modules = {RestModule.class, SocketModule.class}) public interface NetComponent { void inject(MainActivity activity); }
I initialize the two components into my Aplication
public class MyApplication extends Application { DbComponent dBComponent; NetComponent netComponent; @Override public void onCreate() { super.onCreate(); dBComponent = DaggerDbComponent.builder().build(); netComponent = DaggerNetComponent.builder().build(); } public NetComponent getNetComponent() { return netComponent; } public DbComponent getdBComponent() { return dBComponent; } }
With all this defined I use the NetComponent into one activity and the DbCompoment into a second one.
Into the first activity
public class MainActivity extends AppCompatActivity { @Inject RestApi restApi; @Inject SocketApi socketApi; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //... ((MyApplication) getApplication()).getNetComponent().inject(this); //... } }
and into the second
public class SecondActivity extends AppCompatActivity { @Inject DbApi dbApi; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //... ((MyApplication) getApplication()).getdBComponent().inject(this); //... } }
Up to here everything works fine and I got my stuff injected properlty in each activity. But then I have realised that RestApi
and SocketApi
were also required into the SecondActity so I tried to inject them into the activity and here I have doubts and issues.
I modify my NetComponent
to add the following line
void inject(SecondActivity activity);
And I modify my SecondActivity
public class SecondActivity extends AppCompatActivity { @Inject DbApi dbApi; @Inject RestApi restApi; @Inject SocketApi socketApi; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //... ((MyApplication) getApplication()).getdBComponent().inject(this); ((MyApplication) getApplication()).getNetComponent().inject(this); //... } }
After those modifications compiling my project I have the following error
Error:(15, 10) error: com.example.guillaume.testdagger.RestApi cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method. com.example.guillaume.testdagger.SecondActivity.restApi [injected field of type: com.example.guillaume.testdagger.RestApi restApi]
Error:(16, 10) error: com.example.guillaume.testdagger.DbApi cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method. com.example.guillaume.testdagger.SecondActivity.dbApi [injected field of type: com.example.guillaume.testdagger.DbApi dbApi]
So my questions are :
- Where this error comes from?
- How can I use several components to inject fields into one activity
- Am I doing this wrong and what will be the best way to organize components/modules in order to be able to reuse one compoment into an activity already containing another module
- I can fix the error by adding and empty public constructor annotated with @Inject to my api classes but doing this I discoreved that all my fields will be injected into the
SecondActivity
regardless of the component used to invoke theinject
method, is it the right way to do this.