匕首2是初级的(第二部分)

上一部分

目录内容

  1. 实施方法和领域
  2. 匕首中的延迟初始化
  3. 匕首模块。 当匕首听不懂你的话
  4. 摘要命名。 相同类型的多个实例

实施方法和领域

第一部分描述了一种在构造函数级别实现依赖关系的方法。 另外,匕首可以实现字段和方法的依赖关系。 但是,在绝对必要时应使用这些实现。

方法实现示例:

class Car @Inject constructor(private var engine: Engine){ var key: Key? = null @Inject set } class Key @Inject constructor() 

在上面的示例中,为关键字段实现了set方法的依赖关系

字段的实现分为三个阶段:

  1. 将嵌入方法添加到抽象工厂
  2. 定义要实施的字段
  3. 在抽象类匕首实现中使用实现方法来实现依赖关系

显然,为了更容易理解这一点,

1.在我们的抽象类中,为MainActivity添加一个实现方法

 @Component interface DaggerComponent { fun getCar(): Car fun getEngine(): Engine fun getFuel(): Fuel fun inject(act: MainActivity) } 

2.定义应在MainActivity中实现的字段。 注入的字段必须为lateinit var,并且对所有人(公共)可见

 @Injected lateinit var car: Car 

3.我们调用抽象类的添加方法inject()来实现活动字段。

最终,我们的MainActivity类将看起来像一条痕迹。 方式:

 class MainActivity : AppCompatActivity() { @Inject lateinit var car: Car override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) DaggerDaggerComponent.create().inject(this) } } 

匕首中的延迟初始化

如您所知,启动应用程序时,并非总是需要所有类的实例。 这样可以加快首次启动速度,并提高速度。 匕首中有2种类型的嵌入式对象初始化:提供者<>和懒惰<>

提供程序 -首次调用该对象时会进行初始化,并且每次调用都会返回该对象的新实例
惰性 -首次调用时发生初始化,然后返回之前缓存的实例

要使用这些类型的初始化,必须以所需的形式“包装”初始化的对象。

提供者用法示例:

 class Engine @Inject constructor(private var fuel: Fuel){ fun start(){ if(fuel!=null){ print("Started!") }else{ print("No more fuel!") } } } class Car @Inject constructor(private var engine: Provider<Engine>){ var key: Key? = null @Inject set fun startCar(){ engine.get().start() } } class Key @Inject constructor() 

每次调用get()方法时,我们都会获得所需对象的新实例。

使用懒惰的示例:

 class Fuel @Inject constructor() { val fuelType = if(BuildConfig.DEBUG){ "benzine" }else{ "diesel" } } class Engine @Inject constructor(private var fuel: Lazy<Fuel>){ fun start(){ if(fuel!=null){ print("Started with ${fuel.get().fuelType}") }else{ print("No more fuel!") } } } 

每次调用get()方法时,我们都会获得相同的实例。

注意! 在Android Studio中添加惰性视图的get()方法时,该方法可能会用红色下划线,因为 Kotlin具有自己的惰性类。 所以我们导入匕首类

 import dagger.Lazy 

匕首模块。 当匕首听不懂你的话

有时候,匕首无法理解您的意图。 例如,我们的Car类具有一个(接口)Driver类型的字段,该字段由Ivanov类继承

当您尝试使用接口类型实现字段时,会出现错误“没有@ Provides注释的方法就无法提供”。

为了解决这个问题,匕首建议使用模块。 这些模块为匕首提供了无法单独获取的其他信息。 作为模块,您可以使用接口或对象(对象)。

要解决以上问题,请创建一个模块:

 @Module interface DaggerModul { @Binds fun bindDriver(driver: Ivanov): Driver } class Ivanov @Inject constructor(): Driver 

在bindDriver方法中,我们解释了如何用匕首初始化接口。

此外,在组件中,您需要列出所有现有的匕首模块

 @Component(modules = [DaggerModul::class]) interface DaggerComponent { … } 

假设对于我们的Engine类,使用了第三方库圆柱体(接口)的字段。 如果不清楚在运行时将初始化哪个类,那么如何为Dagger描述此类字段?

到目前为止,我们已经使用注释来解释匕首应该如何注入依赖项。 例如,如果您不知道如何从外国图书馆创建类怎么办?

提供注释描述了当您需要显式描述要初始化的类的实例时的情况。

 @Module object DaggerModuleObject { @Provides @JvmStatic fun getBoschCylinder(): Cylinder = BoschCylinder() } 

因此,我们告诉匕首,当初始化圆柱体字段时,我们需要BoschCylinder类的实例。

摘要名为 相同类型的多个实例

有时您需要使用不同的设置来创建同一类的实例。 在我们的示例中,这些是车身和门上的不同颜色。

尝试使用跟踪构建项目时。 模块将收到错误“(我们的类)颜色被绑定多次”

 @Provides @JvmStatic fun getColorRed():Color = Color("red") @Provides @JvmStatic fun getColorBlue():Color = Color("blue") 

为了解决这种情况,使用了Named注释。 首先,在模块中,我们将创建3个新的方法以使用dagger进行初始化

 @JvmStatic @Provides fun getColor(): Color = Color("") @Provides @Named("blueColor") @JvmStatic fun getColorBlue(): Color{ return Color("blue") } @JvmStatic @Named("redColor") @Provides fun getColorRed(): Color = Color("red") 

第一个方法是默认方法,没有它的话,匕首会发誓说缺少类“没有Inject构造函数或Provides注释方法无法提供”

以下两个方法返回相同类的实例。 仍然需要在适当的地方添加此类的实现,并使用命名为Named的注释进行调用

 class Door @Inject constructor() { @Named("blueColor") @Inject lateinit var color:Color } class Car @Inject constructor(private var engine: Provider<Engine>, private var door: Door, var driver: Driver){ var key: Key? = null @Inject set @Inject @Named("redColor") lateinit var color: Color fun startCar(){ engine.get().start() } } class Key @Inject constructor() 

源代码

Source: https://habr.com/ru/post/zh-CN466769/


All Articles