前言
最近在重构项目,用到依赖注入,查了很多资料,这里主要是记录一下自己的理解。
正文
依赖注入的优势:
1.代码的可复用性
2.便于重构
3.易于测试
什么是依赖注入?
依赖注入(DI)是一种广泛的应用编程的技术,非常适合Android开发,通过遵循DI的原则,您可以为良好的应用程序架构打下基础。
类通常需要对其他类的引用, 举个例子,Car(汽车)类可能需要对Engine(引擎)类的引用。这些必需的类称为依赖项,
class Car {
private Engine engine = new Engine();
public void start() {
engine.start();
}
}
class MyApp {
public static void main(String[] args) {
Car car = new Car();
car.start();
}
}
在本例中在没有依赖注入,Car和Engine是紧密耦合的,如果现在定义一个名为ElectricEngine的新引擎类,那么Car类是不可复用的。
那么依赖注入是怎么使用的呢?与Car的每个实例在初始化时构造自己的Engine对象不同,它在构造函数中接收一个Engine对象作为参数
class Car {
private final Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public void start() {
engine.start();
}
}
class MyApp {
public static void main(String[] args) {
Engine engine = new Engine();
Car car = new Car(engine);
car.start();
}
}
Car的可复用性。你可以把不同的引擎实现传递给Car。例如,您可能定义了一个名为ElectricEngine的新引擎子类,希望Car使用它。如果您使用DI,您所需要做的就是传递一个更新后的ElectricEngine子类的实例,Car仍然可以工作,而不需要做任何进一步的更改。
在Android 中有两种主要的依赖注入方式:
1.构造函数注入(上面的例子)。这就是上面描述的方法。将类的依赖项传递给它的构造函数。
2.字段注入(或Setter注入)。某些Android框架类(比如activity和fragments)是由系统实例化的,所以构造函数注入是不可能的。 使用字段注入,依赖项在类创建后实例化。代码如下
class Car {
private Engine engine;
public void setEngine(Engine engine) {
this.engine = engine;
}
public void start() {
engine.start();
}
}
class MyApp {
public static void main(String[] args) {
Car car = new Car();
car.setEngine(new Engine());
car.start();
}
}
注意:依赖项注入基于控制反转原理,其中泛型代码控制特定代码的执行
在前面的示例中,您自己创建、提供和管理不同类的依赖项,而不依赖于库。这称为手动依赖项注入。在Car的例子中,只有一个依赖项,但是更多的依赖项和类会使依赖项的手动注入变得更加繁琐。手动依赖注入也出现了几个问题:
对于大型应用程序,获取所有依赖项并正确地连接它们可能需要大量代码。在多层体系结构中,为了为顶层创建对象,您必须提供它下面的所有层的依赖关系,举个具体的例子,要造一辆真正的汽车,你可能需要一个发动机、一个变速器、一个底盘和其他部件;而发动机则需要气缸和火花塞。那有没有解决这个问题的方案呢?答案是:当然有了,那就是自动依赖注入。
自动依赖注入目前有两种解决方案:
1.在运行时连接依赖项的基于反射的解决方案。
2.在编译时生成连接依赖项的代码的静态解决方案。
Dagger是一个流行的Java、Kotlin和Android的依赖注入库,由谷歌维护。Dagger通过为您创建和管理依赖关系图,为您在应用程序中使用DI提供了便利。它提供了完全静态的和编译时的依赖关系,解决了许多基于反射的解决方案(如Guice)的开发和性能问题。
基于反射的解决方案我们这里不讲,我这里主要是用到的Dagger,下一篇文章我会专门讲解Dagger.
此外本文章如有什么写的不到位的地方,欢迎留言指正!!!