dagger2简单使用与理解笔记
Posted 六道对穿肠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dagger2简单使用与理解笔记相关的知识,希望对你有一定的参考价值。
文章目录
使用dagger2好处
- 解耦.比如需要更换http的框架, 只需要在HttpModule 中更换提供者的对象即可
- 把对象给dagger2管理 更好的管理类实例
- 增加开发效率、省去重复的简单体力劳动 避免不断的去new对象
具体案例查看github
https://github.com/liudao01/IOCProject
1. 使用dagger2注入基本使用流程
- IOC(Inversion of Control):控制反转
在Java开发中。IOC是原来由程序代码中主动获取资源的方式,转变为由第三方获取资源并使原来的代码被动接收资源的方式,以达到解耦的效果,称为控制反转。
概念
2. dagger2中各种注解基本使用
引入dagger2
implementation 'com.google.dagger:dagger:2.35'
annotationProcessor 'com.google.dagger:dagger-compiler:2.35'//APT注解处理器技术, 利用APT生成代码
0. 写两个对象 用来实际操作的
/**
* Created by liuml on 2022/4/14 10:47
*/
public class HttpObject
String TAG = "HttpObject";
public void post()
Log.d(TAG, "HttpObject post: post请求数据 ");
/**
* Created by liuml on 2022/4/14 10:47
*/
public class DataObject
1. 写module类 (注解Module). Provides方法提供对象(Provides注解).
@Module
public class HttpModule
@Provides
public HttpObject providerHttpObject()
return new HttpObject();
2. Component 创建
/**
* Created by liuml on 2022/4/14 10:50
* 组件 用来放module的 需要那些module
*/
@Component(modules = HttpModule.class, DataModule.class)
public interface MyComponent
//这里的参数不能用多态
void inject(MainActivity activity);
3. 在activity里面注入并调用
public class MainActivity extends AppCompatActivity
String TAG = "MainActivity";
//注入后直接用
@Inject
HttpObject httpObject;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMyComponent.create().inject(this);
httpObject.post();
Log.d(TAG, "onCreate: httpObject "+httpObject.hashCode());
//也可以使用建造者模式 方便动态修改参数,传递参数
DaggerMyComponent.builder()
.build()
.inject(this);
打印结果
2022-04-15 10:36:29.807 14293-14293/com.demo.ioc_project D/HttpObject: HttpObject post: post请求数据
2022-04-15 10:36:29.807 14293-14293/com.demo.ioc_project D/MainActivity: onCreate: httpObject 38794633
4. 单例使用
局部单例
如果在model中使用了单例, 那么在Component中也需要使用单例注解
model类
/**
* Created by liuml on 2022/4/14 10:48
*
* 这个类用来提供对象
*/
@Module
public class HttpModule
@Singleton
@Provides
public HttpObject providerHttpObject()
return new HttpObject();
Component组件
/**
* Created by liuml on 2022/4/14 10:50
* 组件 用来放module的 需要那些module
*/
@Singleton
@Component(modules = HttpModule.class, DataModule.class)
public interface MyComponent
//这里的参数不能用多态
void inject(MainActivity activity);
注入使用
public class MainActivity extends AppCompatActivity
String TAG = "MainActivity";
//注入后直接用
@Inject
HttpObject httpObject;
@Inject
HttpObject httpObject2;
private TextView tvTest;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTest = findViewById(R.id.tv_test);
DaggerMyComponent.create().inject(this);
DaggerMyComponent.builder()
.build()
.inject(this);
tvTest.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
DaggerMyComponent.builder()
.build()
.inject(MainActivity.this);
);
httpObject.post();
Log.d(TAG, "onCreate: httpObject " + httpObject.hashCode());
Log.d(TAG, "onCreate: httpObject2 " + httpObject2.hashCode());
//也可以使用建造者模式 方便动态修改参数,传递参数
打印结果
2022-04-15 16:49:49.755 11157-11157/com.demo.ioc_project D/MainActivity: onCreate: httpObject 197891620
2022-04-15 16:49:49.755 11157-11157/com.demo.ioc_project D/MainActivity: onCreate: httpObject2 197891620
两个对象都是一个
全局单例
如果新建一个activity. 在新的activity里面进行注入对象. 如果这个对象用了新的Component注入对象,那么
5. 多个Component组合依赖
在实际项目中,可能存在多个Component,那么需要把代码注入到某个类中,但是dagger2不允许两个或者两个以上的Component注入到同一个类. 这个时候就需要使用组合依赖.
- 依赖方式
一个Component可以依赖一个或者多个Component,采用的是@Component的dependencies属性。
如下
/**
* Created by liuml on 2022/4/14 10:50
* 组件 用来放module的 需要那些module
*/
@Singleton
@Component(modules = HttpModule.class, DataModule.class, dependencies = PresenterComponent.class
)
public interface MyComponent
//这里的参数不能用多态
void inject(MainActivity activity);
void injectSecActivity(SecActivity activity);
- 包含方式
这里就用到了@SubComponent注解,用这个注解标记接口或者抽象类,表示它可以被包含。一个Component可以包含一个或者多个Component,而且被包含的Component还可以继续包含其他的Component。
- 继承方式
注意几点:
-
Component的作用域 必须跟 对应的Module作用域一致。如果@Module没有标记作用域,那就不影响。
-
Component 和 依赖的Component作用域范围不能一样,否则会报错。一般来讲,我们应该对每个Component都定义不同的作用域。
-
@Singleton并不是真的能创建单例,但是我们依然可以保证在App的生命周期内一个类只存在一个对象。@Singleton更重要的作用是通过标记来提醒我们自己来达到更好的管理实例的目的。
作用域@Scope
Dagger2中有一个现成的作用域注解,那就是@Singleton
@Scope 它声明依赖的作用域。换句话说,范围注解是为了定义实例的生命周期,在此生命周期内,实例属于单例模式,一旦离开生命周期,实例将被回收,内存空间得到释放。
简单理解就是:@Scope 注解标记在自定义注解上,指导注入器如何重用实例。
前面讨论的 @Singleton 就是用 @Scope 标记的注解,可以用来生成全局单例依赖。
@Scope 通过标记自定义注解,帮助我们 划分单例所属生命周期。
在 Application 中,使用 @Singleton 内置注解标记全局单例
在 Activity 中,使用 @ActivityScoped 自定义注解标记页面单例
可以认为,@Scope 实际上就是单例模式,只是用不同的命名表示不同的单例生效范围。
使用Scope 注意两点
scope&dependencies的使用
- 多个component上面的scope不能相同
- 没有scope的组件不能去依赖有scope的组件
6. 组合的其他用法
两个 Component 之间除了 dependencies 依赖方式以外,还可以使用 Subcomponent 方式。
和 dependencies 的区别:
被依赖的 Component 不需要显示声明 Module 中对应的 provideXXX() 方法
初始化的时候不需要使用 DaggerXXXComponent 创建被依赖的 Component 对象
dependencies:被依赖的 Component 有 Scope 修饰时,依赖方必须使用 Scope 且不可与前者的 Scope 相同;
Subcomponent:被依赖的 Component 有 Scope 修饰时,依赖方可以不使用 Scope,也可以使用 Scope 但不能与前者的 Scope 相同;
相同点是:被依赖的 Component 没有 Scope 修饰时,依赖方是否使用 Scope 没有要求。
那么使用SubComponent和Component中添加dependencies的区别是啥呢?
Component Dependencies - Use this when:
// 你想保持两个组件之间的独立
you want to keep two components independent.
// 你想强调一个组件是依赖于另一个组件
you want to explicitly show what dependencies from one component is used by the other.
Subcomponents - Use this when:
// 你想让一个组件保持高内聚(不想直接暴露子组件的实例化过程)
you want to keep two component cohesive.
// 你并不在意明确展示出两个组件之间的依赖关系(哪个组件依赖哪个组件)
you may not care to explicitly show what dependencies from one component is used by the other.
3. dagger注入原理源码分析
实际上是通过apt技术生成了代码
如下图
以上是关于dagger2简单使用与理解笔记的主要内容,如果未能解决你的问题,请参考以下文章