gpt4 book ai didi

Dagger2 custom scopes: Are custom scopes not seen on @Inject constructor injections when using provider methods in a module?(Dagger2定制作用域:在模块中使用提供程序方法时,@Inject构造函数注入上看不到定制作用域吗?)

转载 作者:bug小助手 更新时间:2023-10-25 10:07:46 24 4
gpt4 key购买 nike



The following is the code

以下是代码


Custom Annotation classes:

自定义注释类:


@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class CtxMain

@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class MyScope

Component:

组件:


@MyScope
@Component(modules = [ToastMakerModule::class,ActionsModule::class])
interface ActionsComponent {
fun injectIntoMain(activity: MainActivity)
}

Modules (Seperate File are made for each module):

模块(每个模块都有单独的文件):


@Module
class ActionsModule(private var context: Context) {
@Provides
@CtxMain
fun providesContext():Context{
return context
}

@Provides
fun providesSharedPrefs(@CtxMain context: Context): SharedPreferences{
return context.getSharedPreferences("PreferencesFile",Context.MODE_PRIVATE)
}
}

@Module
class ToastMakerModule {
@Provides
fun provideToastMaker(@CtxMain context: Context): ToastMaker{
return ToastMaker(context)
}
}

Models:

型号:


@MyScope
class ToastMaker @Inject constructor(@CtxMain private val context:Context) {
fun showToast(){
Toast.makeText(context,"This is a Toast",Toast.LENGTH_SHORT).show()
}
}

MainActivity:

MainActivity:


class MainActivity : AppCompatActivity() {
@Inject
lateinit var toastMaker: ToastMaker

@Inject
lateinit var toastMaker2: ToastMaker

@Inject
lateinit var sharedPreferences: SharedPreferences

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

DaggerActionsComponent.builder()
.actionsModule(ActionsModule(this))
.build()
.injectIntoMain(this)

toastMaker.showToast()
}
}

Upon running this code the expexted ouptut was that due to @MyScope annotation toastMaker and toastMaker2 should point to the same object but they are not even tough the ToastMaker class has been annotated with @MyScope but still different obejcts are created for each (different hashcodes), but upon modifying the code (removing the provider for ToastMaker) i.e.

在运行这段代码时,扩展的结果是由于@MyScope注释toastaker和toastMaker2应该指向相同的对象,但它们甚至不是坚固的,toastaker类已经用@MyScope注释,但仍然为每个对象创建了不同的bejct(不同的散列码),但是在修改代码时(删除toastaker的提供程序),即


Modified ToastMakerModule (commented the provider)

已修改ToastMakerModule(对提供程序进行了注释)


@Module
class ToastMakerModule {
// @Provides
// fun provideToastMaker(@CtxMain context: Context): ToastMaker{
// Log.d("#D","Provider de ToastMaker")
// return ToastMaker(context)
// }
}

Now when the Field Injection is coming from the ToastMaker Class itself, both toastMaker and toastMaker2 point to the same obejct (same hashcode), What am i missing here? why is provider method not returning me the same instance even tough its marked with @MyScope. i know we can mark the provider method with @MyScope annotation to make provider method return the same instance but shouldnt this work because the ToastMaker class is annotated with @MyScope. when provider method is removed its working fine, why?

现在,当字段注入来自ToastMaker类本身时,toastMaker和toastMaker2都指向相同的bejct(相同的散列码),我在这里遗漏了什么?为什么提供者方法不向我返回相同的实例,甚至很难将其标记为@MyScope。我知道我们可以用@MyScope注释来标记提供者方法,以使提供者方法返回相同的实例,但这不应该起作用,因为toastaker类是用@MyScope注释的。当提供程序方法被移除时,它的工作正常,为什么?


更多回答
优秀答案推荐

Because you've offered Dagger a @Provides method, it will use that and completely ignore the @Inject-annotated constructor and any scopes you list on the class.

因为您已经为Dagger提供了一个@Provides方法,所以它将使用该方法并完全忽略@Inject注释的构造函数和您在类中列出的任何作用域。


As Dagger maintainer Brad Corso mentions in google/dagger#3361 "Singletons are initilized several times when injected into application" (emphasis mine):

正如Dagger的维护者Brad Corso在Google/Dagger#3361中提到的那样,“单例在注入应用程序时会被初始化几次”(重点是我的):



However, even if your actual SubsManager class does have an @Inject-annotated constructor you should still verify it is not provided via a module since bindings provided via a module can implicitly override bindings provided via an @Inject-annotated constructor.



To understand this behavior, it is helpful to think of the @Inject-annotated constructor and class scope annotations as a single definition, just like the @Provides method and its scope annotations are a single definition. Rather than trying to merge the two definitions (using the scope from the class-annotation definition and the implementation from the @Provides method definition), Dagger just observes the scopeless @Provides method definition and entirely overrides the class-annotation definition.

要理解这种行为,将@Inject注释的构造函数和类作用域注释看作单个定义会很有帮助,就像@Provides方法及其作用域注释是单个定义一样。Dagger并没有尝试合并这两个定义(使用来自类注释定义的作用域和来自@Provides方法定义的实现),而只是观察无作用域的@Provides方法定义,并完全覆盖类注释定义。


Dagger behaves as if you are deliberately trying to override the scope on ToastMaker to make it scopeless--which is a particularly reasonable assumption because you can customize your set of modules per Dagger component but you can only define your potentially-reusable ToastMaker class exactly once. If you need to override the class, including scopes defined directly on the class, then a @Provides method on a module is your natural choice and you absolutely wouldn't want the scope definition on the class to be merged into your module override.

Dagger的行为就像是故意试图覆盖toastaker上的作用域,使其成为无作用域--这是一个特别合理的假设,因为您可以为每个Dagger组件定制一组模块,但您只能定义潜在可重用的toastaker类一次。如果您需要覆盖类,包括直接在类上定义的作用域,那么模块上的@Provides方法是您的自然选择,您绝对不希望将类上的作用域定义合并到模块覆盖中。


To fix this problem, you'll need to either remove the @Provides method (such that the @Inject constructor and scope remain together), or add the appropriate @MyScope annotation onto the @Provides method.

要解决这个问题,您需要删除@Provides方法(以便@Inject构造函数和作用域保留在一起),或者在@Provides方法上添加适当的@MyScope注释。


更多回答

Thank you very much for such detailed answer. Kudos to you!

非常感谢您如此详细的回答。向你致敬!

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com