匕首2基类注射

时间:2015-05-07 11:26:56

标签: android dependency-injection dagger-2

在Dagger 1中,我有一个基类设置,以便它可以处理创建一个范围图并将依赖项注入当前对象。例如......

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而不是它的子类注入依赖项。建议?

1 个答案:

答案 0 :(得分: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();
    }
}

编辑:仅当您使用以下模式时,@Subcomponent才能根据the docs使用子组件工厂方法替换组件依赖项(也就是说,将子组件嵌入到父组件中)使用规定/工厂方法定义):

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

     RequestComponent newRequestComponent(RequestModule requestModule);
   }

其中

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