Dagger2单身实际上并不是单身人士的问题

时间:2018-01-15 20:10:13

标签: 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 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
  }
}

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

1 个答案:

答案 0 :(得分:1)

它不是@Singleton因为你没有告诉Dagger它是。你把范围放在演示者身上,如果你使用构造函数注入就可以了,但你不是。

@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声明为单身人士。它将永远使用引擎盖下的单身人士。 (我相信它甚至可能会对两者的范围都有一点点性能损失。)

2。 @Provides method

从类中删除范围(除了混淆之外什么都不做),然后将其放在@Provides方法上。那就是它。

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

构造函数注入类的范围,或@Provides方法的范围(如果您正在使用它)。不要混淆它们。

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