当前位置:网站首页>Dagger2从0基础使用,到单例注入的正确姿势
Dagger2从0基础使用,到单例注入的正确姿势
2022-08-09 14:55:00 【按劳分配】
Dagger2从0基础使用,到单例注入的正确姿势
- 环境搭建
- 基本流程
- 四个基础注解 @Inject @Module @Provides @Component
- 实现单例的两种注入方式
一、环境搭建
1、工程的gradle文件配置
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
2、module的gradle文件配置
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
compile 'com.google.dagger:dagger:2.7'
apt 'com.google.dagger:dagger-compiler:2.7'
}
二、 基本流程
Dagger2使用编译时注解apt,通过apt,通过生成工具类将注入的需求者和注入的提供者联系起来,在我们需要给注入的需求者注入的地方,调用生成的工具类,传入注入的需求者,工具类自己就可以去查找提供者来进行注入。
借图一张(http://www.jianshu.com/p/c556b415b800) 
三、四个基础注解
1、 @Inject (标记属性或者构造函数)
作用1:在类中给属性标记注解,表明这个属性需要Dagger2来给我注入
作用2:在构造函数上面标记注解,表明这个构造函数是注入的提供者,可以提供该对象的注入
2、 @Module(标记类)
作用:说明该类是一个注入的提供者类
3、 @Provides(标记方法)
作用:说明该方法是注入的提供者,方法的返回值就是提供的注入的对象
4、 @Component(标记类)
作用:将注入的需求者和提供者联系起来
先来实现一个最简单的注入:
第一个类SimpleObj 注入提供者
public class SimpleObj {
public String objName;
@Inject//构造函数有这个注解
public SimpleObj(){
objName = "名字来源于注入";
}
}
第二个类,注入的需求者,不能用private修饰
public class MainActivity extends AppCompatActivity {
@Inject
SimpleObj simpleObj;//属性被Inject注解标记,
@Override
protected void onResume() {
super.onResume();
Log.i("aaa",simpleObj.objName);//没有实例化simpleObj 直接输出
}
这个时候运行肯定崩溃,我们自己还没有注入呢。
第三个类 注入的入口,也就是联系人
/**
* Created by limengjie
* on 2017/3/30.17:30
*/
@Component()//这个标记必须
public interface SimpleComponent {
void inject(MainActivity m);//这个方法必须
}
在联系人这里,我们只看到了注入需求者,没有看到提供者,这是因为没有系统会自动去查找的,多有的注入者Dagger2都是知道的,这里先不去关心这个问题。
第四个步骤,rebulid一下
如果成功,会在app\build\generated\source\apt 目录下面生成一些文件,其中就有需求提供者的身影,最重要的联系人SimpleComponent,变成了DaggerSimpleComponent
第五个步骤,在MainAcitivity中注入
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initInject();
}
public void initInject(){
DaggerSimpleComponent.builder().build();
}
最后运行结果
03-30 09:47:12.686 28281-28281/? I/aaa: 名字来源于注入
如果认真完成了上面的步骤,会觉得注入这么简单,那是因为还有几个注解没用上@Module、 @Singleton和@Component的属性dependencies与modules。
5、@Component的属性dependencies与modules。
第一步改造
@Module
public class SimpleObj {
public String objName;
@Inject
public SimpleObj(){
objName = "名字来源于注入";
}
@Provides
public SimpleObj provideSimpleObj(){
return new SimpleObj();
}
}
这样它就可以写到@Component的属性module里面
第二步改造,在component中加入module
@Component(modules = SimpleObj.class)
public interface SimpleComponent {
void inject(MainActivity m);
}
当然会想,我不要这个都可以注入,我要他来何用,且看rebulid后生成的代码
public final class DaggerSimpleComponent implements SimpleComponent {
private MembersInjector<MainActivity> mainActivityMembersInjector;
public static final class Builder {
private SimpleObj simpleObj;
private Builder() {}
public SimpleComponent build() {
if (simpleObj == null) {
this.simpleObj = new SimpleObj();
}
return new DaggerSimpleComponent(this);
}
public Builder simpleObj(SimpleObj simpleObj) {
this.simpleObj = Preconditions.checkNotNull(simpleObj);
return this;
}
}
这里 public Builder simpleObj(SimpleObj simpleObj)方法多出来,也就是这个注入的提供者,我们可以自己传入了
对比以前的:
public static final class Builder {
private Builder() {}
public SimpleComponent build() {
return new DaggerSimpleComponent(this);
}
}
我们在使用的时候
DaggerSimpleComponent.builder().simpleObj(new SimpleObj()).build().inject(this);
这样我们在通过component注入的时候,可以自己传入提供者。
四、实现单例注入
方式一injcet构造函数注入:
1、提供者
@Singleton //这个注解可以换成自己的随便都可以
public class SimpleObj {
public String objName;
@Inject
public SimpleObj(){
objName = "名字来源于注入";
}
// @PerActivityXX3
// @Provides
// public SimpleObj provideSimpleObj(){
// return new SimpleObj();
// }
}
2、中间人
@Singleton//这里的注解必须和提供者注解范围一致,可以自定义随便写,但是要一致才可以
@Component()
public interface SimpleComponent {
void inject(MainActivity m);
}
public class MainActivity extends AppCompatActivity {
@Inject
SimpleObj simpleObj;
@Inject
SimpleObj simpleObj2;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
appCompoent = DaggerAppCompoent.builder().jiaMoudle(new JiaMoudle("")).build();
initInject();
}
public void initInject(){
DaggerSimpleComponent.builder().build().inject(this);
}
@Override
protected void onResume() {
super.onResume();
Log.i("aaa",simpleObj.toString());
Log.i("aaa",simpleObj2.toString());
}
输出结果
I/aaa: [email protected]5d
I/aaa: [email protected]5d
现在这整个MainActiviy中实现了单例,要想全局单例,只需要把DaggerSimpleComponent.builder().build()返回的SimpleComponent实例全局单例存起来,就可以,在其他需要注入SimpleObj的地方调用SimpleComponent实例来注入就全局单例了。
方式二、module提供provides注解的方法
1.提供者
@Module
public class SimpleObj {
public String objName;
public SimpleObj(){
objName = "名字来源于注入";
}
@Singleton
@Provides
public SimpleObj provideSimpleObj(){
return new SimpleObj();//每次注入都是new的,单例的话只会调用一次这里,下次回去缓存查找
}
}
2、中间人
@Singleton
@Component(modules = SimpleObj.class)
public interface SimpleComponent {
void inject(MainActivity m);
}
3、注入需求者mainactivity不变
public class MainActivity extends AppCompatActivity {
@Inject
SimpleObj simpleObj;
@Inject
SimpleObj simpleObj2;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
appCompoent = DaggerAppCompoent.builder().jiaMoudle(new JiaMoudle("")).build();
initInject();
}
public void initInject(){
DaggerSimpleComponent.builder().build().inject(this);
}
@Override
protected void onResume() {
super.onResume();
Log.i("aaa",simpleObj.toString());
Log.i("aaa",simpleObj2.toString());
}
输出结果,
I/aaa: [email protected]5d
I/aaa: [email protected]5d
注意:
标记只有@Singleton,可以实现单例,但是它的范围只是在compoent的生命周期内,如果你在新bulid一个component,那么他提供注入的实例就不和以前一样了。
全局单例:必须要@Singleton,且compoent也是全局单例存在,这样提供的注入就是全局单例了。
并且,@Singleton这个范围标记可以换成自定义的范围标记,@Singleton只是见名只意罢了,换成其他的范围标记是一样的,Dagger的范围标记提供了compoent声明周期内的单例,具体要扩展到全局单例还是其他的范围,只需要把compoent的声明周期控制就行了。
总结
要想实现全局单例,注入者提供者必须全局单例存在,提供注入的方法必须给定范围,component的范围和moudle方法范围一致,如果是构造函数inject,则这个类必须标记一致的范围。
边栏推荐
- Matlab修改Consolas字体
- 双摄像头系列原理深度剖析【转载】
- Several important functions of singly linked list (including insertion, deletion, reversal, etc.)
- Talking about Shallow Cloning and Deep Cloning of ArraryList
- 量子力学初步
- 你知道亚马逊代运营的成本是多少吗?
- 排序方法(希尔、快速、堆)
- OpenCV简介与搭建使用环境
- In the process of quantitative trading, retail investors can do this
- 【C语言初阶】倒置字符串(输入 I like beijing. 输出beijing. like I)
猜你喜欢
随机推荐
升职加薪之SQL索引
自定义指令,实现默认头像和用户上传头像的切换
Sequelize配置中的timezone测试
跨平台桌面应用 Electron 尝试(VS2019)
What are the misunderstandings about the programmatic trading system interface?
How to make your quantitative trading system have probabilistic advantages and positive return expectations?
What are the hot topics in quantitative programmatic trading?
Sort method (Hill, Quick, Heap)
Qt control - QTextEdit usage record
Linux安装mysql8.0详细步骤--(快速安装好)
Entity Framework Core知识小结
浏览器指纹识别是什么意思?
九、【Vue-Router】缓存路由组件 keep-alive标签
工作不等于生活,但生活离不开工作 | 2022 年中总结
C#轻量级ORM使用 Dapper+Contrib
How to achieve long-term benefits through the Tongdaxin quantitative trading interface?
【小白必看】初始C语言(下)
NoUniqueBeanDefinitionException和JSON乱码处理出现异常
为什么要学编译原理
CV复习:过拟合、欠拟合









