代码之家  ›  专栏  ›  技术社区  ›  Hafez Divandari

如何在Android中使用Dagger2更容易注入活动对象?

  •  1
  • Hafez Divandari  · 技术社区  · 7 年前

    在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 回复  |  直到 7 年前
        1
  •  1
  •   jaychang0917    7 年前

    这种“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. 把你的 s、 所以它可以在步骤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

        2
  •  1
  •   fweigl    7 年前