Зависимости от двух компонентов в одном действии

Я играю с 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, это правильный путь сделать это.

person Guillaume Barré    schedule 01.04.2016    source источник


Ответы (1)


Ах... я разделяю твою боль. Вы не можете внедрить два компонента в одно и то же действие. По крайней мере я не смог найти как! :)

Это было логично и для меня попробовать, и я столкнулся с теми же проблемами.

Вы можете решить это с помощью 2 подходов:

  1. Используйте один большой компонент для всех инъекций (я действительно против этого)
  2. Создайте по одному компоненту для каждого действия/места, в которое вы хотите что-то внедрить.

Итак, вместо

@Singleton
@Component(modules = {RestModule.class, SocketModule.class})
public interface NetComponent {
   void inject(MainActivity activity);
}

попробуй с

@Singleton
@Component(modules = {RestModule.class, SocketModule.class, DbModule.class})
public interface SecondActivityComponent {
   void inject(SecondActivity activity);
}

Я нашел второй как самое чистое решение.

Если у кого-то есть другие советы, я готов попробовать!

person Bozic Nebojsa    schedule 01.04.2016