项目作者: MaYunFei

项目描述 :
研究Dagger的Scope
高级语言: Java
项目地址: git://github.com/MaYunFei/DaggerScopeDemo.git
创建时间: 2017-12-23T14:25:52Z
项目社区:https://github.com/MaYunFei/DaggerScopeDemo

开源协议:Apache License 2.0

下载


研究 Dagger的Scope 为什么 @Singleton 可以起到单例的作用

文件结构
├── components
│ ├── ActivityComponent.java
│ └── AppComponent.java
├── modules
│ └── AppModule.java
└── scopes
├── AppScope.java
└── PerActivity.java

起因

在项目中想使用一个全局变量,以前只是设计一个单例对象即可(static 全局变量),但是静态全局变量对代码侵入很严重,还是想通过注入的方式使用,就直接在 AppModule 中添加了一个 Provides 但是使用时并没有起到单例的作用,之前还以为只要在 AppModule 中添加就会像是在 Application 中创建一样。

@Singleton

又想到了使用 Dagger 中的 @Singleton 注解,直接在 AppModule 中添加 @Singleton
报错

  1. Error:(16, 1) 错误: com.example.yunfei.dagger.components.AppComponent (unscoped) may not reference scoped bindings:
  2. @Singleton @Provides com.example.yunfei.GlobalVariable com.example.yunfei.dagger.modules.AppModule.provideGlobalVariable()

必须在 AppModle 中也添加 @Singleton ,加完之后还是有问题

  1. Error:(12, 1) 错误: com.example.yunfei.dagger.components.ActivityComponent (unscoped) cannot depend on scoped components:
  2. @Singleton com.example.yunfei.dagger.components.AppComponent

ActivityComponent 没有作用域,就不能依赖一个有作用域的 Component ,当然你不能也给 ActivityComponent 也弄 @Singleton 也是会报错的,(可能是因为如果是同一个作用域就逻辑上就不应该分成两个 Component 这点我也不清楚,应该看下源码)
最终给 ActivityComponent添加了一个 @PerAcivity的作用域

  1. this.provideGlobalVariableProvider = DoubleCheck.provider(AppModule_ProvideGlobalVariableFactory.create(builder.appModule));

原因在于 DoubleCheck

  1. public T get() {
  2. Object result = instance;
  3. if (result == UNINITIALIZED) {
  4. synchronized (this) {
  5. result = instance;
  6. if (result == UNINITIALIZED) {
  7. result = provider.get();
  8. /* Get the current instance and test to see if the call to provider.get() has resulted
  9. * in a recursive call. If it returns the same instance, we'll allow it, but if the
  10. * instances differ, throw. */
  11. Object currentInstance = instance;
  12. if (currentInstance != UNINITIALIZED && currentInstance != result) {
  13. throw new IllegalStateException("Scoped provider was invoked recursively returning "
  14. + "different results: " + currentInstance + " & " + result + ". This is likely "
  15. + "due to a circular dependency.");
  16. }
  17. instance = result;
  18. /* Null out the reference to the provider. We are never going to need it again, so we
  19. * can make it eligible for GC. */
  20. provider = null;
  21. }
  22. }
  23. }
  24. return (T) result;
  25. }