2015-09-01 2 views
5

Конфигурация моего кинжала для проекта android, над которым я работаю: Примечание: Я предоставил все необходимые @Component, @Module, @Provides аннотации везде, где это необходимо.Множественный независимый компонентный впрыск

MainActivity { 

@Inject A a; 
@Inject B b; 

onCreate(){ 
    ComponentX.inject(this); 
    ComponentY.inject(this); 
} 
} 

ComponentX-> ModuleA ->providerA 
ComponentY -> ModuleB -> providerB 

Как вы можете видеть, это две совершенно независимые компоненты, не связанные друг с другом в любом случае, за исключением в месте инъекции.

Во время компиляции я получаю следующее сообщение об ошибке:

In file A.java 
error: B cannot be provided without an @Provides- or @Produces-annotated method. 
MainActivity.b 
[injected field of type: B b] 

я ошибаюсь, думая, что несколько компонентов могут быть использованы при использовании кинжала 2 или приложение должно использовать один большой компонент, который заботится о всех инъекции?

Может кто-нибудь помочь мне понять, где я иду не так?

ответ

7

Вы не должны иметь один компонент, существуют различные способы модуляризировать их, но каждый объект, который вы создаете, или вводить значения в, должны иметь все свои ценности, предоставляемые одним компонентом.

Один из способов, которым вы могли бы перестроить свой код, - это иметь компонент ComponentY в зависимости от ComponentX или наоборот.

@Component(dependencies = ComponentX.class) 
interface ComponentY { 
    void inject(MainActivity activity); 
} 

Или вы можете создать третий компонент, скажем ComponentZ, если ComponentX и ComponentY полностью ортогональны друг другу.

@Component(dependencies = {ComponentX.class, ComponentY.class}) 
interface ComponentZ { 
    void inject(MainActivity activity); 
} 

Или вы можете просто повторно использовать модули, например.

@Component(modules = {ModuleA.class, ModuleB.class}) 
interface ComponentZ { 
    void inject(MainActivity activity); 
} 

Как именно вы решили разбить его во многом зависит от структуры вашего кода. Если компоненты X и Y видны, но модули тогда не используют зависимостей компонентов, так как они (и модульные зависимости) являются на самом деле деталями реализации компонента. В противном случае, если модули видны, просто повторите их повторное использование.

Я бы не использовал области для этого, так как они действительно предназначены для управления объектами с различными скоростями жизни, например. объекты, связанные с конкретным пользователем, срок службы которого - время, с которого пользователь входит в систему при выходе из системы, или срок службы конкретного запроса. Если у них разная продолжительность жизни, вы смотрите на использование областей и подкомпонентов.

+0

Метод композиции - это то, что я сделал в настоящее время как промежуточное решение. С другой стороны, с моей точки зрения, области применения были разными, как вы упомянули. То, что я хотел идентифицировать, было то, был ли это подходящий подход, компонент целевой целевой цели, который представляет собой состав из нескольких компонентов (которые предоставляются в библиотечных проектах). – gaara87

+0

Это определенно хороший подход, независимо от того, подходит ли вам правильный подход. Опять же, это зависит от того, что такое «api» и как вы хотите его модулировать. –

+0

Это, безусловно, хороший подход, будь то правильный подход зависит от вас. Опять же, это зависит от того, что такое «api» и как вы хотите его модулировать. –

0

is the application supposed to use one big component which takes care of all the injections?

Вы можете использовать Subcomponent. В ваших компонентов случае декларация будет выглядеть следующим образом:

@Subcomponent(modules=ModuleB.class) 
public interface ComponentY{ 
    void inject(MainActivity mainActivity); 
} 

@Component(modules=ModuleA.class) 
public interface ComponentX{ 
    ComponentY plus(ModuleB module); 
} 

ComponentY создание: creationCompunentY = ComponentX.plus(new ModuleB());

Сейчас в MainActivity вы называете только ComponentY.inject(this);

MainActivity { 

@Inject A a; 
@Inject B b; 

onCreate(){ 
    ComponentY.inject(this); 
} 
} 

Более подробная информация о вспомогательных компонентах можно найти в migration from Dagger1 guide (посмотрите часть подграфов), Subcomponent JavaDoc и Component JavaDoc (см. часть подкомпонентов).

+0

В этом случае вы говорите о том, чтобы составить все это в один большой компонент, который заботится об инъекциях. Вы не имеете дело со сценарием наличия двух отдельных компонентов. Имея два отдельных инъекции – gaara87

+0

Я думаю, что составление конечного компонента перед его использованием намного лучше, чем выполнение нескольких инъекций, как вы предлагаете. Ваша «MainActivity» не должна знать, как распределяются ваши зависимости между «Компонентами». Есть два или три компонента и т. Д. И вы можете изменить это распределение, чтобы обеспечить более легкое тестирование или простое повторное использование без изменения «MainActivity». – MyDogTom

+0

@MyDogTom Я не согласен с тем, что составление одного «жирного» компонента лучше. Я хотел бы, чтобы свобода вводила вещи прямо в класс. В обоих случаях MainActivity не имеет понятия о создании компонентов и заботится только о том, что им вводится. Я не говорю, что вы ошибаетесь, просто это другая перспектива взгляда, но я вижу это как ограничение. –

2

is the application supposed to use one big component

Вид, вы должны подумать об этом в областях. Для данной области существует один компонент. Областями применения являются, например, ApplicationScope, FragmentScope (не заполнено), ActivityScope, ViewScope. Для каждой области есть данный компонент; области не разделяются между компонентами.

(Это по существу означает, что если вы хотите иметь глобальные синглтоны в @ApplicationScope, для него есть один компонент с областью действия. Если вам нужны классы, специфичные для действий, то вы создаете для него компонент для этой конкретной деятельности, будет зависеть от компонента, охваченного приложением).

Обратитесь к @MyDogTom за аннотацией @Subcomponent, но вы также можете использовать зависимости компонентов для создания подкопных компонентов.

@YScope 
@Component(dependencies = ComponentX.class, modules=ModuleB.class) 
public interface ComponentY extends ComponentX { 
    B b(); 

    void inject(MainActivity mainActivity); 
} 

@XScope 
@Component(modules=ModuleA.class) 
public interface ComponentX{ 
    A a(); 
} 

ComponentY componentY = DaggerComponentY.builder().componentX(componentX).build(); 
+0

1) Скомпилирован ли он для вас? Потому что это две разные области. 2) Вы в конечном счете говорите об одном компоненте здесь, расширяя компонент Y от компонентаX. Вы взяли маршрут наследования, и я думал о маршруте композиции (выбирая межкомпонентную зависимость). – gaara87

+0

Конечно, он компилируется, если вы добавляете две аннотации пользовательских областей, YScope - подкласс XScope. Think ActivityScope - это подкласс ApplicationScope. – EpicPandaForce

Смежные вопросы