如何在Android中使用Dagger2轻松注入活动对象?

时间:2018-08-24 20:31:13

标签: android dagger-2

在Android上,使用Dagger2时,我必须在使用apiService的每个活动上调用以下行:

@Inject
public ApiService apiService;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    DaggerApiComponent.builder()
                      .activityModule(new ActivityModule(this))
                      .build()
                      .inject(this);

    //...
}

如何将其总结为:

DaggerApiComponent.builder()
                  .activity(this)
                  .build()
                  .inject(this);

或更简单:

MyApplication.injectApiService(this);

如何在活动中更改组件和模块以使用带有较少复制粘贴代码的Dagger2?

这是我的ApiComponent

@Singleton
@Component(modules = ApiModule.class)
public interface ApiComponent {

    void inject(MainActivity activity);
    void inject(...
}

这里是ApiModule

@Module(includes = {RetrofitModule.class, ActivityModule.class})
public class ApiModule {

    @Singleton
    @Provides
    public static ApiService provideApiService(Activity activity) {
        //...
    }
}

ActivityModule

@Module
public class ActivityModule {

    private final Activity context;

    public ActivityModule(Activity context) {
        this.context = context;
    }

    @Singleton
    @Provides
    public Activity provideActivityContext() {
        return context;
    }
}

2 个答案:

答案 0 :(得分:1)

您可以使用Android Activity注射器,用法here进行了详细说明。

答案 1 :(得分:1)

这种“ DI”的方法有两个问题:

  • 就像OP所说的那样:我们需要在需要注射的任何地方复制并粘贴此样板,这既繁琐又难于重构。
  • 被注入者(例如Activity)不应该知道@Inject实例的来源,它关心的只是“嘿,给我一个实例”。

为解决上述问题,dagger.android来了。

  1. 为每个组件创建AndroidInjector
// App component
@Singleton
@Component(
    modules = [
        AndroidSupportInjectionModule::class, // build-in module
        ActivityBindingModule::class,            
        AppModule::class
    ]
)
interface AppComponent : AndroidInjector<MainApplication> {
    // we need to bind `MainApplication` instance to this component,
    // so we have a builder here.
    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<MainApplication>()
}
// Each controller (e.g. `Activity` / `Fragment` / `Service`) subcomponents
@Module
abstract class ActivityBindingModule {
    // will generate a FooActivitySubcomponent under ActivityBindingModule's component
    @ActivityScoped
    @ContributesAndroidInjector(modules = [FooModule::class])
    internal abstract fun fooActivity(): FooActivity

    @ActivityScoped
    @ContributesAndroidInjector(modules = [BarModule::class])
    internal abstract fun barActivity(): BarActivity
}
  1. 连接您的AndroidInjector,以便可以使用步骤1中提供的注射器为我们进行注射。
// App component
class MainApplication : DaggerApplication() {

    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
        return DaggerAppComponent.builder().create(this)
    }
}
// Each controller subcomponents
class FooActivity : DaggerAppCompatActivity() {
    @Inject lateinit var foo: Foo

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState) 
        // no need to call inject() here anymore!
        foo.doSth()
    }
}

举一个具体的例子:签出iosched