了解Dagger 2 @ Component.Builder注释

Ton*_*Joe 11 android components dagger-2

我正在阅读这个很棒的教程,解释了@Component.BuilderDagger 2中的工作方式.作者做得很好,文章很简单,但我仍需要澄清一些令人困惑的事情:Dagger 2的默认实现看起来像这样:

组件:

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {

  void inject(MainActivity mainActivity);
  SharedPreferences getSharedPrefs();
}
Run Code Online (Sandbox Code Playgroud)

模块:

@Module
 public class AppModule {

    Application application;

    public AppModule(Application application) {
       this.application = application;
    }

    @Provides
    Application providesApplication() {
       return application;
    }
    @Provides
    @Singleton
    public SharedPreferences providePreferences() {
        return application.getSharedPreferences(DATA_STORE,
                              Context.MODE_PRIVATE);
    }
}
Run Code Online (Sandbox Code Playgroud)

组件实例化:

DaggerAppComponent appComponent = DaggerAppComponent.builder()
         .appModule(new AppModule(this)) //this : application 
         .build();
Run Code Online (Sandbox Code Playgroud)

根据文章,我们可以通过避免使用@Component.Builder@BindsInstance注释向模块构造函数传递参数来进一步简化此代码,然后代码将如下所示:

组件:

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
   void inject(MainActivity mainActivity);
   SharedPreferences getSharedPrefs();

   @Component.Builder
   interface Builder {
      AppComponent build();
      @BindsInstance Builder application(Application application);      
  }
Run Code Online (Sandbox Code Playgroud)

}

模块:

@Module
 public class AppModule {

     @Provides
     @Singleton
     public SharedPreferences providePreferences(
                                    Application application) {
         return application.getSharedPreferences(
                                    "store", Context.MODE_PRIVATE);
     }
 }
Run Code Online (Sandbox Code Playgroud)

并且组件实例化:

DaggerAppComponent appComponent = DaggerAppComponent.builder()
           .application(this)
           .build();
Run Code Online (Sandbox Code Playgroud)

我几乎不懂上面的代码是如何工作的,但这里是我不明白的一部分:我们是怎么从获取appModule(new AppModule(this))application(this),当我们实例化的组件?

我希望这个问题很明确,谢谢.

Dav*_*jak 17

tl; dr Dagger将自己创建任何无参数构造函数模型,如果您不传递它们,并且@BindsInstance可能比从模块提供类型更好地优化使用.


首先,你有一个需要Application构建的组件.因此,您构建模块并将其传递给组件.

现在,使用组件构建器,您可以单个对象绑定到组件.这是我们上面所做的替代方案.不再需要模块,我们可以直接将Dagger交给我们在组件中所需的对象.
正如@Binds提供界面实现一样,您通常可以假设Dagger可以并且将优化使用模块的简单方法之类的功能,因为意图更明确.

因此,使用@BindsInstance将添加类型到我们的组件,以便我们不再需要模块来提供它.我们现在也可以从模块构造函数中删除参数.

当我们实例化组件时,我们是如何从appModule(新的AppModule(this))到应用程序(this)的?

由于Dagger本身可以实例化no-args模块,因此不再需要将模块显式添加到组件中,我们可以用新.application(this)调用替换该行.


Nid*_*hin 6

 @Component.Builder
   interface Builder {
      AppComponent build();
      @BindsInstance Builder application(Application application);      
  }
Run Code Online (Sandbox Code Playgroud)

当我们调用方法

应用程序(应用程序)

从应用程序类

.应用程序(这个)

它会将我们的应用程序对象设置为 AppComponent。因此,在 appcomponet 中,应用程序实例可用。

所以我们可以从应用程序模块中删除以下代码,因为 dagger 会在需要的地方自动注入应用程序实例。

Application application;
   public AppModule(Application application) {
       this.application = application;
    }

    @Provides
    Application providesApplication() {
       return application;
    }
Run Code Online (Sandbox Code Playgroud)

此外,Dagger 使用默认构造函数实例化所有模块。

如果你想要一个来自 AppModule 的 Context 对象,只需写

@Module
public class AppModule {

   @Provides
    Context provideContext(Application application) {
        return application;
    }
}
Run Code Online (Sandbox Code Playgroud)