Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/206.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Dagger2单例实际上不是单例问题_Android_Dependency Injection_Dagger 2 - Fatal编程技术网

Android Dagger2单例实际上不是单例问题

Android Dagger2单例实际上不是单例问题,android,dependency-injection,dagger-2,Android,Dependency Injection,Dagger 2,我有一个对象,我正试图使用@inject注释将它作为一个单体注入到3个片段中 组成部分: @Subcomponent(modules = [(MyModule::class)]) interface MyComponent { fun inject(fragment: OneFragment) fun inject(fragment: TwoFragment) fun inject(fragment: ThreeFragment) } 模块: @Module class MyM

我有一个对象,我正试图使用
@inject
注释将它作为一个单体注入到3个片段中

组成部分:

@Subcomponent(modules = [(MyModule::class)])
interface MyComponent {

  fun inject(fragment: OneFragment)
  fun inject(fragment: TwoFragment)
  fun inject(fragment: ThreeFragment)

}
模块:

@Module
class MyModule(val view: MyView) {

  @Provides
  fun provideView(): MyView = view

  @Provides
  fun providePresenter(view: MyView,
                       myService: MyService): MyPresenter =
      MyPresenterImpl(view, myService)

}
MyPresenterImpl:

@Singleton
class MyPresenterImpl(override val view: MyView,
                      override val myService: MyService): MyPresenter {

  private val TAG = javaClass.simpleName

  // other code (irrelevant)
}
片段:

class OneFragment : Fragment() {

  @Inject
  lateinit var myPresenter: MyPresenter

  override fun onCreateView(inflater: LayoutInflater, viewGroup: ViewGroup?,
                            bundle: Bundle?): View? {
    activity?.mainApplication?.appComponent?.plus(
        MyModule(activity as MyActivity))?.inject(this)

    val view = inflater.inflate(R.layout.fragment_one, viewGroup, false)

    //other meaningless code

    return view
  }
}

但是,注入片段的演示者不是同一个唯一实例。我做错了什么?

它不是一个
@Singleton
,因为你没有告诉Dagger它是。您将作用域放在了presenter上,如果您使用的是构造函数注入,这将很好,但是您没有

@Singleton // does nothing. you're not doing constructor injection.
class MyPresenterImpl(override val view: MyView,
                  override val myService: MyService): MyPresenter


// ...and in your module...


@Provides // where's the scope? it's unscoped.
fun providePresenter(view: MyView,
                  myService: MyService): MyPresenter =
    MyPresenterImpl(view, myService)
所以你有两个选择。要么使用构造函数注入,要么使用
@Provides
。你不能随便挑选和使用每一个

1.构造函数注入 只需删除模块中带有注释的
@Provides
方法,并在构造函数上插入
@Inject

@Singleton // NOW we're doing constructor injection -> singleton!
class MyPresenterImpl @Inject constructor(override val view: MyView,
                  override val myService: MyService): MyPresenter
现在不需要模块来声明它。如果要将其绑定到接口,可以使用
@Binds
注释并继续使用构造函数注入

@Binds // bind implementation to interface
abstract fun providePresenter(presenter : MyPresenterImpl) : MyPresenter
由于
MyPresenterImpl
是一个
@Singleton
,因此您不必将
MyPresenter
也声明为一个Singleton。它将始终使用引擎盖下的singleton。(我相信在这两个方面都使用scopes可能会带来更大的性能损失。)

2. <代码>@提供了方法 将作用域从类中移除(在类中它只会混淆),并将其放在
@Provides
方法中。就这样

@Singleton // singleton!
@Provides
fun providePresenter(view: MyView,
                  myService: MyService): MyPresenter =
    MyPresenterImpl(view, myService)

类上的作用域用于构造函数注入,或者
@上的作用域提供了
方法(如果您正在使用该方法)。不要把它们混在一起


我个人建议尽可能使用constructor injetion,因为您不必自己管理/更新构造函数调用。

您可能不是从超级作用域组件继承presenter,而是为每个子组件创建一个新的presenter。这不是使用@Singleton的地方。@Singleton应该标记provider方法,告诉Dagger返回的值是Singleton。可以在Presenter类上使用
@Singleton
。事实上,square建议将范围注释作为“实现细节”放在实现中的位置。请参阅的“偏好@injectover@Provides”部分。问题是您还应该使用
@Inject
注释该构造函数。把所有的东西都放在一个地方。singleton不是仅仅是一个范围注释,并且仅仅意味着组件范围中只有一个对象吗?由于每个片段都在创建一个新组件,因此在出现
@提供的情况下将创建一个新的presenter对象,但是,在堆栈溢出的每个其他答案中,我如何区分
@Singleton
和'Singleton',并指出它们之间的区别将导致比它所能防止的更多的混淆<代码>@Singleton
在dagger的上下文中,总是意味着每个
@Singleton
作用域组件都有一个实例,但通常只有一个,这就是为什么它在大多数情况下最终会成为一个实际的Singleton。这种解决方案是错误的。将注入放在构造函数上并不意味着它将自动注入到使用lateinit var myPresenter:myPresenter的类中-在成员变量上使用lateinit绝对需要使用组件,而组件又需要模块。因此,与您声称不需要任何模块相反,它是必需的。@AndroidDev拥有一个
@Inject
注释构造函数,使Dagger能够提供/注入依赖项,就像
@提供带注释的方法、
@Binds
方法或
@BindsInstance
生成器方法一样。我并没有说Dagger会自动执行任何操作,
lateinit
是一个Kotlin构造,与Dagger本身无关,我想你是说场注入?当然,您需要一个组件,但组件不需要模块。这里不是讨论的地方,所以如果你有具体问题,请提出新问题并提供更多细节。