匕首2基类注射匕首

2023-09-06 00:55:39 作者:时光与梦相遇

在匕首1我有一个基类的设置,这样它会处理创建范围的图形和依赖注入到当前对象。例如...

In Dagger 1 I had a base class setup such that it would handle creating a scoped graph and injecting dependencies into the current object. For example...

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 */];
  }
}

这允许每个子类,以补充其自己的一组模块中除了一个标准应用模块。

This allowed for each subclass to supplement their own set of modules in addition to a standard application module.

在用匕首2玩弄,它似乎并不能够处理类似的情景......

After playing around with Dagger 2, it doesn't seem possible to handle a similar scenario...

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这样它会列出它所有可能​​用到的模块...

I worked around the above by modifying MyBaseActivityComponent such that it would list all possible modules it may use...

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

所以,现在我可以做这样的事情...

So now I can do something like this...

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但不是它的子类。建议?

But now I have a problem where the injection will inject dependencies for MyBaseActivity but not it's subclasses. Suggestions?

推荐答案

从理论上讲,你能做到这样。

Theoretically, you can do it like this.

1)指定的子范围

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

2。)指定的父组件

2.) Specify the parent component

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

3。)指定的子组件

3.) Specify the child component

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

    Dependency3 providesDependency3();
}

4。)创建你的模块

4.) Create your module

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

5。)创建活动级别范围的组件

5.) Create Activity-level scoped component

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();
    }
}

请回复,如果它的工作,previously我忘了指定在我的组件的依赖关系,并得到了编译错误,但它应该像这样工作。

Please reply if it worked, previously I forgot to specify the dependencies in my Component and got compile errors, but it should work like this.

另外,如果你需要指定一个子组件每个活动,那么你可以指定与在 BaseActivityComponent 部分...

Also, if you need to specify a subcomponent for each Activity, then you can just specify the dependencies with provision methods in the BaseActivityComponent component...

@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 工程与子工厂方法根据的的文档只有当您使用以下方式(即,使用条款/工厂方法嵌入父组件中的子组件定义):

EDIT: @Subcomponent works to replace component dependencies with subcomponent factory methods according to the docs only if you use the following pattern (aka, embedding the subcomponent within the parent component using a provision/factory method definition):

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

     RequestComponent newRequestComponent(RequestModule requestModule);
   }

其中,

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