临时构造函数注入与依赖注入框架

时间:2019-06-13 06:39:36

标签: android dependency-injection

好的,所以我决定仔细研究一下在我的项目中实现junit测试。 然后,我偶然发现了一篇文章,其中写到了使用诸如 Dagger2 Koin 这样的依赖注入框架来简化测试的重要性。

我尝试阅读-什么是 DI 。我将其理解为解决A类依赖对象(例如B类和C类)的一种方式。

我现在通常要做的是:

在活动中,我创建ViewModelViewModel需要访问数据,因此对于数据,我拥有SomeRepository类。然后,我通常通过SomeRepository构造函数或使用属性注入传递ViewModel。据我了解,如果我没记错的话,那也是某种依赖注入(如果我记错了,请纠正我)。

那么,如果我现在开始使用Dagger 2,我将获得什么好处?也许简单的代码比较会使它更清晰?预先感谢。

活动:

val someRepository = SomeRepository()
viewModel.init(someRepository) 

在ViewModel中:

class SomeViewModel : ViewModel {

    private lateinit var repository: SomeRepository

    fun init(val someRepo: SomeRepository) {
        this.repository = someRepo
    }

}

2 个答案:

答案 0 :(得分:5)

Dagger通过其自己的依赖关系图促进依赖关系的解耦。我们需要告诉匕首类如何生成例如它需要一个构造函数参数。定义后,它将遍历所有依赖项并从低级别开始创建它们。如果我们不能在构造函数中注入任何依赖关系,例如改造后,我们可以手动告诉dagger如何使用@Provides注释创建if的实例。

让我们看一个例子:

第1个依存关系-个性化方式

@Module
class NetworkModule {

 @Provides
 fun provideRetrofit() : Retrofit  

}

依赖项2 -取决于依赖项1

class ApiService constructor (@Inject retrofit: Retrofit){
}

依赖性#3 -取决于依赖性#2

class SomeRepository constructor (@Inject apiService: ApiService){
}

依赖性#4 -取决于依赖性#3

class SomeViewModel constructor (@Inject someRepository: SomeRepository) : ViewModel {
}

Dagger将在运行时生成所有依赖项。当您运行应用程序时,每个依赖项已准备就绪,可以直接注入构造函数中。您还可以通过字段注入

注入任何依赖项
class MainAcitivty : AppCompatActivity(){

 @Inject someRepository: SomeRepository

}

符合您当前的做法:

val someRepository = SomeRepository()
viewModel.init(someRepository) 
  1. 您将在不同的活动中反复创建SomeRepository()的新实例
  2. 如果SomeRepository()具有任何依赖关系,这些依赖关系还将创建多次
  3. 您正在紧密耦合。如果没有SomeRepository()的依赖项,将很难测试。在单元测试中,我们有兴趣测试单元而不是其依赖项。

答案 1 :(得分:1)

Pro1:用外行的话来说,DI对于编写解耦的代码很重要,这使编写单元测试变得容易。

Pro2:它还从父类中抽象出对象的依赖关系。例如,在您的用例中,Activity不是直接使用SomeRepository,而是仍然需要了解它。但是,相反,如果您像这样使用构造函数注入:

class SomeViewModel constructor (@Inject someRepository: SomeRepository) : ViewModel {
}

您的活动类只需要处理SomeViewModel对象,而SomeViewModel使用的任何依赖项都不在乎。

Pro3:DI使创建和访问单例对象变得非常容易。 只需定义一个如下所示的类,即可在应用程序中的任何位置获取MySingleton类的单个实例。

@Singleton
class MySingleton @Inject constructor() {}

OR

@Provides @Singleton mySingleton() {}