【问题标题】:Understanding Dagger 2 @Component.Builder annotation理解 Dagger 2 @Component.Builder 注解
【发布时间】:2018-02-22 03:46:39
【问题描述】:

我正在阅读 this 很棒的教程,该教程解释了 @Component.Builder 如何在 Dagger 2 中工作。作者做得很好,文章直截了当,但我仍然需要澄清一些令人困惑的地方:默认实现Dagger 2 看起来像这样:

组件:

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

  void inject(MainActivity mainActivity);
  SharedPreferences getSharedPrefs();
}

模块:

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

组件实例化:

DaggerAppComponent appComponent = DaggerAppComponent.builder()
         .appModule(new AppModule(this)) //this : application 
         .build();

根据文章,我们可以通过避免使用@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);      
  }

}

模块:

@Module
 public class AppModule {

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

以及组件实例化:

DaggerAppComponent appComponent = DaggerAppComponent.builder()
           .application(this)
           .build();

上面的代码我差不多明白了,但我不明白的部分是:当我们实例化组件时,我们是如何从appModule(new AppModule(this))application(this) 的?

我希望问题很清楚,谢谢。

【问题讨论】:

    标签: android components dagger-2


    【解决方案1】:

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


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

    现在,使用组件构建器,您只需将单个对象绑定 到组件。这是我们上面所做的替代方法。不再需要模块,我们可以直接将我们想要在组件中的对象交给 Dagger。
    正如@Binds 提供接口实现一样,您通常可以假设 Dagger 可以并且将比使用模块的简单方法更好地优化这些功能,因为其意图被更清楚地标记。

    所以使用@BindsInstance 会将类型添加到我们的组件中,这样我们就不再需要模块来提供它了。我们现在还可以从模块构造函数中移除参数。

    当我们实例化组件时,我们是如何从 appModule(new AppModule(this)) 到 application(this) 的?

    由于 Dagger 可以自己实例化无参数模块,因此不再需要显式地将模块添加到组件中,我们可以用新的 .application(this) 调用替换该行。

    【讨论】:

    • 如果 Dagger 可以自己实例化 no-args 模块,我们就直接使用DaggerAppComponent.builder().build();,那么appliction(this) 是干什么用的?
    • 检查您的Component.Builder 界面!您注册了一个将应用程序绑定到组件的方法,您必须调用该方法:@BindsInstance Builder application(Application application);
    • 现在我明白了!非常感谢 David Medenjak,你很有帮助
    【解决方案2】:
     @Component.Builder
       interface Builder {
          AppComponent build();
          @BindsInstance Builder application(Application application);      
      }
    

    当我们调用方法时

    应用程序(应用程序应用程序)

    来自应用类

    .application(这个)

    它将我们的应用程序对象设置为 AppComponent。所以在 appcomponet 内部,应用程序实例是可用的。

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

    Application application;
       public AppModule(Application application) {
           this.application = application;
        }
    
        @Provides
        Application providesApplication() {
           return application;
        }
    

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

    如果您想要 AppModule 中的 Context 对象,只需编写

    @Module
    public class AppModule {
    
       @Provides
        Context provideContext(Application application) {
            return application;
        }
    }
    

    【讨论】:

    • 最后一个 sn-p 的意义何在?如果客户想要来自 AppModule 的上下文,他们为什么不直接使用他们传入的参数
    • 如果你使用@Inject Context 上下文;在你的活动中。只有当它的模块提供 Context 对象时它才会起作用
    • 没关系,我误解了您对 sn-p 的原始观点,您只是想表达您将如何从 AppModule 注入。不知道有没有办法不通过AppModule中的参数来获取应用实例的引用
    • 我认为您可以为此使用@Binds。 keisar 对此答案的回答可能会有所帮助stackoverflow.com/questions/30692501/…。我还没试过。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-01
    • 2020-09-02
    • 1970-01-01
    • 2019-04-10
    相关资源
    最近更新 更多