我有一个对象,我试图使用 @Inject
注释将其作为单例注入(inject)到 3 个 fragment 中。
组件:
@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)
}
fragment :
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
}
}
但是,注入(inject)到 fragment 中的演示者并不是同一个唯一实例。我做错了什么?
最佳答案
它不是 @Singleton
因为你没有告诉 Dagger 它是。您将范围放在演示者上,如果您使用构造函数注入(inject),这会很好,但您没有。
@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)
所以你有两个选择。要么使用构造函数注入(inject),要么使用@Provides
。您不能择优挑选并使用每一种。
1。构造函数注入(inject)
只需删除模块中的 @Provides
注解方法,然后在构造函数上添加 @Inject
即可。
@Singleton // NOW we're doing constructor injection -> singleton!
class MyPresenterImpl @Inject constructor(override val view: MyView,
override val myService: MyService): MyPresenter
现在不需要模块声明它。如果您想将其绑定(bind)到接口(interface),您可以使用@Binds
注释并继续使用构造函数注入(inject)...
@Binds // bind implementation to interface
abstract fun providePresenter(presenter : MyPresenterImpl) : MyPresenter
由于 MyPresenterImpl
是一个 @Singleton
,因此您不必将 MyPresenter
声明为单例。它将始终在幕后使用单例。 (我相信在两者上进行作用域时甚至可能会产生稍大的性能损失。)
2。 @Provides方法
从类中删除作用域(除了混淆之外什么也不做),并将其放在 @Provides
方法上。就是这样。
@Singleton // singleton!
@Provides
fun providePresenter(view: MyView,
myService: MyService): MyPresenter =
MyPresenterImpl(view, myService)
构造函数注入(inject)的类范围,或者 @Provides
方法的范围(如果您正在使用该方法)。不要混淆它们。
我个人建议尽可能进行构造函数注入(inject),因为您不必自己管理/更新构造函数调用。
关于android - Dagger2 单例实际上并不是单例问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48270000/