2015-05-07 9 views
3

В кинжале 1 У меня была установка базового класса, так что она обрабатывала бы создание графа с областью и впрыскивание зависимостей в текущий объект. Например ...Dagger 2 инъекции базового класса

public abstract class MyBaseActivity extends Activity { 
    private ObjectGraph graph; 

    protected void onCreate(Bundle savedInstanceState) { 
    graph = ((MyApp) getApplication()).plus(getModules()); 
    graph.inject(this); 
    } 

    protected Object[] getModules(); 
} 

public class MyClass extends MyBaseActivity { 

    @Inject SomeDep someDep; 

    @Override 
    protected Object[] getModules() { 
    return new Object[/* Contains a module that provides SomeDep */]; 
    } 
} 

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

После того, как играл с Dagger 2, это не представляется возможным обрабатывать подобный сценарий ...

public abstract class MyBaseActivity extends Activity { 
    private MyBaseActivityComponent component; 

    protected void onCreate(Bundle savedInstanceState) { 
    component = ((MyApp) getApplication()).component().plus(/* Can not accept an array */); 
    component.inject(this); 
    } 
} 

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

@Subcomponent(modules = { 
    Module1.class, 
    Module2.class 
}) 
public interface MyBaseActivityComponent { 
    public void inject(MyBaseActivity activity); 
} 

Так что теперь я могу сделать что-то вроде этого ...

public abstract class MyBaseActivity extends Activity { 
    private MyBaseActivityComponent component; 

    protected void onCreate(Bundle savedInstanceState) { 
    component = ((MyApp) getApplication()).component().plus(new Module1(), new Module2()); 
    component.inject(this); 
    } 
} 

Но теперь у меня есть проблема, когда инъекция будет зависеть от зависимостей для MyBaseActivity, но не от подклассов. Предложения?

+0

убедитесь вызвать 'super.onCreate (savedInstanceState);' – EpicPandaForce

ответ

2

Теоретически вы можете сделать это вот так.

1.) Указать дочерний объем

@Scope 
@Retention(RUNTIME) 
public @interface PerActivity { 
} 

2.) Выбрать родительский компонент

@Singleton 
@Component(modules={Module1.class, Module2.class) 
public interface MyApplicationComponent { 
    Dependency1 providesDependency1(); 
    Dependency2 providesDependency2(); 
} 

3.) Указать дочерний компонент

@PerActivity 
@Component(dependencies={MyApplicationComponent.class}, modules={Module3.class}) 
public interface MyBaseActivityComponent extends MyApplicationComponent { 
    void inject(BaseActivity baseActivity); 

    Dependency3 providesDependency3(); 
} 

4.) Создать ваш модуль

@Module 
public class Module3 { 
    @Provides 
    @PerActivity 
    public Dependency3 providesDependency3() { 
     return new Dependency3(); 
    } 
} 

5.) Создание активности на уровне области видимости компонент

public class BaseActivity extends AppCompatActivity { 
    private MyBaseActivityComponent baseComponent; 

    @Override 
    public void onCreate(Bundle saveState) { 
     super.onCreate(saveState); 
     baseComponent = DaggerBaseActivityComponent.builder() 
        .applicationComponent(((MyApp)getApplication()).component()) 
        .build(); 
    } 

    public MyBaseActivityComponent baseComponent() { 
     return baseComponent; 
    } 

    @Override 
    public void onDestroy() { 
     component = null; 
     super.onDestroy(); 
    } 
} 

Пожалуйста, ответьте, если он работал, ранее я забыл указать зависимости в моем Component и получил ошибки компиляции, но она должна работать, как это.

Кроме того, если вам нужно указать субкомпонент для каждого Activity, то вы можете просто указать зависимости с помощью методов предоставления в BaseActivityComponent компоненте ...

@PerActivity 
@Component(dependencies={MyBaseActivityComponent.class}, modules={Module4.class}) 
public interface MyActivityComponent extends MyBaseActivityComponent { 
    public void inject(MyActivity myActivity); 

    Dependency4 providesDependency4(); 
} 

@Module 
public class Module4 { 
    @PerActivity 
    @Provides 
    public Dependency4 providesDependency4(Dependency3 dependency3) { 
     return new Dependency4(dependency3); 
    } 
} 

public class MyActivity extends MyBaseActivity { 
    private MyActivityComponent component; 

    @Override 
    public void onCreate(Bundle saveInstanceState) { 
     super.onCreate(saveInstanceState); 
     component = DaggerMyActivityComponent.builder() 
      .applicationComponent(((MyApp)getApplication()).component()) 
      .myBaseActivityComponent(baseComponent()) 
      .build(); 
    } 

    @Override 
    public void onDestroy() { 
     component = null; 
     super.onDestroy(); 
    } 
} 

EDIT: @Subcomponent работает, чтобы заменить компонент зависимостей с заводскими методами субкомпонента в соответствии с the docs, только если вы используете следующий шаблон (например, встраивание подкомпонента в родительский компонент с использованием определения условия/фабричного метода):

@Singleton @Component 
    interface ApplicationComponent { 
    // component methods... 

    RequestComponent newRequestComponent(RequestModule requestModule); 
    } 

Где

@Subcomponent(modules={RequestModule.class}) 
    interface RequestComponent { 
     RequestSomething requestSomething(); 
    } 
+0

«mkay, готовый, хотя я напечатал это от верхней части моей головы, и я надеюсь, что это работает. – EpicPandaForce

+0

Это не устраняет необходимость правильного ввода инъекций?Каждому подклассу BaseActivity по существу нужно будет вызвать 'component.inject'. –

+0

Да, к сожалению. Я попытался ввести «BaseJob» в очередь на приоритет орфографии, но он, похоже, не работал. – EpicPandaForce

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