компоненты должны быть «большой поставщик DI», который обеспечивает все необходимое для определенной области.
Например, вы можете иметь SingletonComponent
с @Singleton
объем, который имеет в каждый отдельный модуль добавленный к нему, что имеет, по меньшей мере, один @Singleton
Scoped метод провайдера.
@Singleton
@Component(modules={NetworkingModule.class, DatabaseModule.class, MapperModule.class, UtilsModule.class})
public interface SingletonComponent {
// provision methods
OkHttpClient okHttpClient();
RealmHolder realmHolder();
// etc.
}
У вас могут быть методы предоставления, определенные для каждого модуля.
public interface DatabaseComponent {
RealmHolder realmHolder();
}
public interface NetworkingComponent{
OkHttpClient okHttpClient();
}
В этом случае вы бы
@Singleton
@Component(modules={NetworkingModule.class, DatabaseModule.class, MapperModule.class, UtilsModule.class})
public interface SingletonComponent
extends NetworkingComponent, DatabaseComponent, MapperComponent, UtilsComponent {
// provision methods inherited
}
В модуле вы можете указать фабричный метод («метод поставщик»), который определяет, как создать конкретный тип зависимости.
Например,
@Module
public class NetworkingModule {
@Provides
@Singleton
OkHttpClient okHttpClient() {
return new OkHttpClient.Builder()./*...*/.build();
}
@Provides
@Singleton
Retrofit retrofit(OkHttpClient okHttpClient) {
// ...
}
}
Вы можете представить себе @Singleton
области как большой DI контейнер, что весна дала бы вам.
Вы также можете предоставить экземпляры класса с помощью @Inject
аннотированный конструктор. Это может получить любой класс из компонента, который может создавать его из методов поставщика в рамках модулей этого облачного компонента (и, конечно, не зависимых от него зависимостей).
@Singleton
public class MyMapper {
@Inject
public MyMapper(RealmHolder realmHolder, OkHttpClient okHttpClient) { // totally random constructor for demo
}
}
или
@Singleton
public class MyMapper {
@Inject
RealmHolder realmHolder;
@Inject
OkHttpClient okHttpClient;
@Inject
public MyMapper() {
}
}
Тогда это будет доступно в компоненте, вы можете даже сделать метод резерва для того, чтобы сделать его наследуемым в зависимости компонентов:
@Singleton
@Component(modules={...})
public interface SingletonComponent {
MyMapper myMapper();
}
С Dagger2 вы также можете добавить создайте «подкопированные компоненты», которые наследуют все зависимости, предоставляемые от компонента данной области.
Например, вы можете наследовать все облачные компоненты @Singleton
, но у вас все еще есть новые зависимые области для этой новой области, такие как @ActivityScope
.
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}
Затем вы можете создавать подкопные компоненты, используя либо подкомпоненты, либо зависимости компонентов.
.
@ActivityScope
@Subcomponent(modules={MainActivityModule.class})
public interface MainActivityComponent {
MainPresenter mainPresenter();
}
Тогда это может быть создано в ее материнской области действия компоненты:
@Singleton
@Component(modules={...})
public interface SingletonComponent {
MainActivityComponent mainActivityComponent(MainActivityModule module);
}
Затем вы можете использовать компонент одноплодного для создания экземпляра этого:
SingletonComponent singletonComponent = DaggerSingletonComponent.create();
MainActivityComponent mainActivityComponent = singletonComponent.mainActivityComponent(new MainActivityModule(mainActivityHolder));
.
@ActivityScope
@Component(dependencies={SingletonComponent.class}, modules={MainActivityModule.class})
public interface MainActivityComponent extends SingletonComponent {
MainPresenter mainPresenter();
}
Для этого, чтобы работать, вы должны указать методы положения в superscoped компоненте.
Тогда вы можете создать экземпляр этого так:
SingletonComponent singletonComponent = DaggerSingletonComponent.create();
MainActivityComponent mainActivityComponent = DaggerMainActivityComponent.builder()
.singletonComponent(singletonComponent)
.mainActivityModule(new MainActivityModule(mainActivityHolder))
.build();
В Dagger2, вы можете таким образом получить зависимости либо через:
@Inject
аннотированных параметров конструктора
@Inject
аннотированные поля на класах сес с @Inject
аннотированным конструктором
- из
@Component
методов предоставления
- через ручной метод инъекционного поля, определенный в компоненте (для классов, которые вы не можете создать с помощью
@Inject
аннотированного конструктора)
Руководством инъекционного поля может произойти для классов, как MainActivity
, что вы сами не создаете.
Ввод вручную вводит только определенный класс, который вы вводите. Базовые классы не вводятся автоматически, они должны вызывать .inject(this)
на компоненте.
Это работает так:
@ActivityScope
@Subcomponent(modules={MainActivityModule.class})
public interface MainActivityComponent {
void inject(MainActivity mainActivity);
}
Тогда вы можете сделать:
public class MainActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
MainActivityComponent mainActivityComponent = DaggerMainActivityComponent.builder()
.singletonComponent(getSingletonComponent())
.mainActivityModule(new MainActivityModule(this))
.build(); // ensure activity `holder` instead, and retain component in retained fragment or `non-configuration instance`
mainActivityComponent.inject(this);
}
}
это сделало его более ясным, у меня все еще есть некоторые сомнения, но я постараюсь разобраться с этим. Мой единственный вопрос - мне все еще нужно создать компонент/подкомпонент для каждого фрагмента/действия в моем приложении? –
У вас нет ** **, я сделал 3 приложения, которые используют только один компонент @ @ Singleton и другие компоненты. – EpicPandaForce