Я играю с Dagger-2, чтобы понять, как интегрировать его в наше существующее приложение, и я столкнулся с чем-то, что я не могу понять или делаю неправильно.
Моя ситуация :
3 API без какого-либо аннотированного конструктора (каждый в своем файле)
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 модуля (каждый в своем файле)
@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 компонента (каждый в своем файле)
@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);
}
Я инициализирую два компонента в своем приложении
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;
}
}
Со всем этим я использую NetComponent в одном действии и DbCompoment во втором.
В первую деятельность
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);
//...
}
}
и во второй
public class SecondActivity extends AppCompatActivity {
@Inject DbApi dbApi;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
((MyApplication) getApplication()).getdBComponent().inject(this);
//...
}
}
До сих пор все работало нормально, и я правильно вводил свои вещи в каждое действие. Но потом я понял, что RestApi
и SocketApi
также требуются в SecondActity, поэтому я попытался внедрить их в активность, и здесь у меня возникли сомнения и проблемы.
Я изменяю свой NetComponent
, чтобы добавить следующую строку
void inject(SecondActivity activity);
И я модифицирую свой 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);
//...
}
}
После этих модификаций при компиляции моего проекта у меня возникла следующая ошибка
Ошибка: (15, 10) ошибка: com.example.guillaume.testdagger.RestApi не может быть предоставлен без конструктора @Inject или из метода с аннотациями @Provides или @Produces. com.example.guillaume.testdagger.SecondActivity.restApi [введенное поле типа: com.example.guillaume.testdagger.RestApi restApi]
Ошибка: (16, 10) ошибка: com.example.guillaume.testdagger.DbApi не может быть предоставлен без конструктора @Inject или из метода с аннотациями @Provides или @Produces. com.example.guillaume.testdagger.SecondActivity.dbApi [введенное поле типа: com.example.guillaume.testdagger.DbApi dbApi]
Итак, мои вопросы:
- Откуда эта ошибка?
- Как я могу использовать несколько компонентов для ввода полей в одно действие
- Я делаю это неправильно и как лучше организовать компоненты/модули, чтобы иметь возможность повторно использовать один компонент в действии, уже содержащем другой модуль?
- Я могу исправить ошибку, добавив и очистив общедоступный конструктор, аннотированный @Inject, в мои классы API, но при этом я обнаружил, что все мои поля будут введены в
SecondActivity
независимо от компонента, используемого для вызова методаinject
, это правильный путь сделать это.