1.Dagger

降低对象的耦合度

Dagger2(不好用)为了后面学习 hilt(对Dagger2的二次封装)

还是APT技术,ARouter,DataBinding,Room,基本上 都是APT编译期生成代码

apt kapt

概述

Dagger目的为能够注入到任何你想要的对象;
Dagger2 可以减低(程序中对象的)耦合度 (解耦

IOC 控制反转
lOC (Inversion of Control)
是原来由程序代码中主动获取的资源,
转变由第三方获取并使原来的代码被动接收的方式,
以达到解耦的效果,称为控制反转

理解

有100个Activity使用Student,或者,100其他地方使用Student,如果Student的实
例方式修改了,那么你都需要修改100次

违背——对扩展开放,对修改关闭

1
2
3
4
5
// 耳机
public class Student {
String name = "Derry";
Student(int value) { }
}

依赖Dagger2来注入对象

Dagger就相当于买快递

好处:

  • 好处一:隔离,相对于对Student对象进行了封装包裹管理,发生变换的只有一处地方;
  • 好处二:之前模式(目标要去管理Student 产生关系) Dagger(目标 和 对象 都需要交给Dagger

使用步骤

第一步 导入依赖

1
2
3
4
//导入API支持 包括注解
implementation 'com.google.dagger:dagger:2.4'
//使用Dagger2的注释处理器APT
annotationProcessor 'com.google.dagger:dagger-compiler:2.4'

第二步 对象

如下是 obj

1
2
3
4
5
6
7
8
9
public class HttpObject {

//可加可不加
@Inject //标记 代表此对象HttpObject 是被注入的来源HttpObject MainActivity是目标
public HttpObject(){

}
}
public class DatabaseObject {}

第三步 module(包裹)

如下是 module

  • @Module
  • @Provides
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 这个类用来提供对象
*/
@Module
public class HttpModule {
@Provides
public HttpObject providerHttpObject(){
return new HttpObject();
}
}

/**
* 这个类用来提供对象
*/
@Module
public class DatabaseModule {
@Provides
public DatabaseObject providerDatabaseObject(){
return new DatabaseObject();
}
}

第三步 component(快递员)

如下是 component

  • 接口
  • @Component(modules = {HttpModule.class, DatabaseModule.class})
1
2
3
4
5
6
7
//组件 接口
@Component(modules = {HttpModule.class, DatabaseModule.class})
public interface MyComponent {
//这里的参数是不能用多态
void injectMainActivity(MainActivity activity);
void injectMainActivity2(MainActivity2 activity2);
}

第四步 使用

如下是 ui

  • @Inject
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class MainActivity extends AppCompatActivity {
@Inject
HttpObject httpObject; // = new HttpObject()
@Inject
HttpObject httpObject2;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// 方式一
DaggerMyComponent.create().injectMainActivity(this);
// 方式二
DaggerMyComponent.builder()
.httpModule(new HttpModule())
.databaseModule(new DatabaseModule())
.build()
// 到这里,初始化了module和component
.injectMainActivity(this);

Log.i("derry", httpObject.hashCode() + " MainActivity");
Log.i("derry", httpObject2.hashCode() + " MainActivity");
}

public void click(View view) {
startActivity(new Intent(this, MainActivity2.class));
}
}


public class MainActivity2 extends AppCompatActivity {
@Inject
HttpObject httpObject;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);

// 方式一
DaggerMyComponent.create().injectMainActivity2(this);
Log.i("derry", httpObject.hashCode() + " MainActivity2");
}
}

局部单例

添加三处 @Singleton

  • Module类上
  • Module中的方法上
  • component接口类上

全局单例(多用)

在 MyApplication 中的 onCreate 方法中只初始化一次

  • 需要添加三处**@Singleton**

  • 添加 MyApplication

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class MyApplication extends Application {
    private MyComponent myComponent;

    @Override
    public void onCreate() {
    super.onCreate();
    //在application中只初始化一次
    myComponent= DaggerMyComponent.builder()
    .httpModule(new HttpModule())
    .databaseModule(new DatabaseModule())
    .build();
    }
    public MyComponent getAppComponent(){
    return myComponent;
    }
    }
  • 使用方式三注入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class MainActivity2 extends AppCompatActivity {
    @Inject
    HttpObject httpObject;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);
    // 方式三
    ((MyApplication)getApplication())
    .getAppComponent()
    .injectMainActivity2(this);
    Log.i("derry", httpObject.hashCode() + " MainActivity2");
    }
    }

源码分析

手写 API

1
2
//导入API支持 包括注解
implementation 'com.google.dagger:dagger:2.4'
1
2
3
4
5
6
//快递员角色注解
@Target(TYPE)
@Retention(RUNTIME)
public @interface Component {
Class<?>[] modules() default {}; //modules属性 默认值为空数组{}
}

包裹注解:

1
2
3
4
5
6
7
8
9
//包裹注解
@Target(TYPE)
@Retention(RUNTIME)
public @interface Module {}

//包裹的暴露注解
@Target(TYPE)
@Retention(RUNTIME)
public @interface Provides {}

用户注入对象角色的注解

1
2
3
@Target({CONSTRUCTOR,FIELD})
@Retention(RUNTIME)
public @interface Inject {}

原理

Dagger 2 是一个用于 Android 和 Java 应用程序的依赖注入框架。它通过生成代码来实现依赖注入,提供了高效、轻量级的解决方案。下面是 Dagger 2 的实现原理的主要要点:

1. 依赖注入基本概念

依赖注入(Dependency Injection, DI)是一种软件设计模式,它允许将对象所依赖的其他对象(即依赖)在运行时传递给它,而不需要在对象内部硬编码这些依赖。这有助于提高代码的可测试性和可维护性。

2. Dagger 2 的工作原理

Dagger 2 的工作原理可以分为以下几个部分:

2.1 注解处理器

Dagger 2 使用注解处理器来生成依赖注入所需的代码。通过使用特定的注解(如 @Module, @Provides, @Inject),Dagger 2 会在编译时生成一个包含依赖关系的类。

2.2 组件(Component)

  • 组件是 Dagger 2 的核心,负责连接提供依赖的模块和请求依赖的类。
  • 通过定义一个接口并使用 @Component 注解来创建一个组件,然后在这个接口中声明需要注入的类(即使用 @Inject 注解的类)。

2.3 模块(Module)

  • 模块是一个提供依赖的类,使用 @Module 注解标记。
  • 在模块中,可以定义提供依赖的方法,并使用 @Provides 注解标记。这些方法会返回具体的依赖实例。

2.4 注入(Injection)

  • 使用 @Inject 注解标记构造函数或字段来表明需要进行依赖注入的地方。
  • 在组件中定义注入方法,传入需要注入的类的实例,Dagger 2 会自动处理依赖关系,并将所需的依赖注入到指定的位置。

3. 依赖的解析

在编译时,Dagger 2 解析所有的依赖关系,并生成所需的代码文件。生成的代码会进行优化,保证性能优越,避免了反射带来的性能损耗。

4. 生命周期管理

Dagger 2 能够与 Android 生命周期很好地集成,可以在 Activity、Fragment 和 Service 等组件中注入依赖,通过依赖于 Android 的生命周期来管理依赖的生命周期。

5. 优缺点

优点

  • 编译时检查依赖关系,减少运行时错误。
  • 无需使用反射,性能更好。

缺点

  • 学习曲线相对较陡,尤其对于初学者。
  • 需要理解注解和依赖注入的设计模式。

通过上述分析,可以了解到 Dagger 2 是如何通过注解处理、组件和模块的结合,来实现高效的依赖注入的。这使得开发者能够编写更加模块化和可维护的代码。

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2023-2025 Annie
  • Visitors: | Views:

嘿嘿 请我吃小蛋糕吧~

支付宝
微信