您如何将由AndroidInjector注入的android对象(服务,活动...)重新注入其他对象?

时间:2019-06-25 15:16:27

标签: android dagger-2

我有一个具有DaggerServiceComponent的服务,该服务将成功注入所有Services依赖项。

问题是我还有一个ServiceManager类,该类需要引用服务才能“管理”服务任务。即

应用

  public class ApplicationBase extends Application implements HasServiceInjector {

    @Inject
    DispatchingAndroidInjector<Service> dispatchingAndroidServiceInjector;

    protected void setupServiceComponent(Context context) {
        ServiceContextModule serviceContextModule = new ServiceContextModule(context);
        ServiceComponent serviceComponent = DaggerServiceComponent.builder().serviceContextModule(serviceContextModule).build();
        serviceComponent.inject(this);

    }


    @Override
    public AndroidInjector<Service> serviceInjector() {
        return dispatchingAndroidServiceInjector;
    }

}

组件

@Singleton
@Component(modules = {  /* modules */})
public interface ServiceComponent extends AndroidInjector<ApplicationBase > {

    ServiceManager provideServiceManager();
    void inject(ApplicationBase appBase);
    // ..
}

模块

@Module
public abstract class MediaPlaybackServiceModule {

    @ContributesAndroidInjector
    abstract MediaPlaybackService provideMediaPlaybackService();

}

MediaPlaybackService MyService

public class MediaPlaybackService extends MediaBrowserServiceCompat {
   // ...
  private ServiceManager serviceManager;

  @Override
  public void onCreate() {
    init();
    super.onCreate();
    // ...
  }
  /**
   * TO BE CALLED BEFORE SUPER CLASS
   */
  private void init() {
    AndroidInjection.inject(this);
    serviceManager.setMediaPlaybackService(this);
  }

  //...
  // declaration of other dependencies
}

如果您查看当前当前的操作,我会手动向setter方法添加一个调用,以在成功注入的ServiceManager类中设置“服务”引用。

服务管理器类如下所示:

public class ServiceManager {

    @Inject
    public ServiceManager(MediaSessionAdapter mediaSession,
                          MyNotificationManager myNotificationManager) {
        this.mediaSession = mediaSession;
        this.notificationManager = myNotificationManager;
    }

    // BODY OF CLASS

    public void setMediaPlaybackService(MediaPlaybackService mediaPlaybackService) {
        this.service = mediaPlaybackService;
    }
}

但是我理想地希望服务管理器构造器看起来像

@Inject
public ServiceManager(MediaPlaybackService mediaPlaybackService, MediaSessionAdapter mediaSession,
                      MyNotificationManager myNotificationManager) {
    this.service = mediaPlaybackService;
    this.mediaSession = mediaSession;
    this.notificationManager = myNotificationManager;
}

我需要对dagger2代码进行哪些更改才能实现此目标?

注意:为简单起见,我删除了应用程序中使用的多余代码,但可以找到它们here

1 个答案:

答案 0 :(得分:0)

因此,对于所有面临与自己相似的问题的人,我已经对dagger-android进行了大量实验,发现执行以下操作变得更加简单:

1)使活动抽象化

public abstract MainActivity extends AppCompatActivity {
  ...
  abstract void initDependencies();
  ...

  @Inject
  public void setMyDependency(MyDependency myDependency) { ... }
}

2)创建一个子类来初始化您的依赖项,从而删除Activity中的匕首依赖项

public MainActivityProduction extends MainActivity  {
  @Override
  void initDependencies() {
     DaggerMainActivityComponent.factory().create(..., this)
     .inject(this);
  }
  @Override
  public void onCreate() {
    initDependencies();
    super.onCreate();
  }
}

请注意,这允许使用一个单独的组件,该组件可按照匕首文档https://dagger.dev/testing中的建议用于测试,即

public MainActivityTesting extends MainActivity  {
  @Override
  void initDependencies() {
     DaggerMainActivityTestingComponent.factory().create(..., this)
     .inject(this);
  }
  @Override
  public void onCreate() {
    initDependencies();
    super.onCreate();
  }
}

3)因此,您的组件将如下所示:

@Component(modules = { /* modules */})
public interface MainActivityComponent {
  ...
  @Component.Factory
  interface Factory {
    MainActivityComponent create(...,
                    @BindsInstance MainActivity);
  }
}

意味着您可以让任何模块引用您的MainActivity

@Module
public class MyDependencyModule {

  @Provides
  public MyDependency providesMyDependency(MainActivity MainActivity) {
     return new MyDependency(mainActivity);
  }
}

此解决方案:

  1. 使样板设置代码与主代码脱钩
  2. 允许轻松实现测试实现
  3. 删除对Application类的依赖关系以设置依赖关系。