前言
项目开撸阶段,准备接入Dagger2,再重新学起来!
这篇文章主要是记录对dagger2的学习,从基本使用,到实际运用,由浅入深。以及dagger2的一些变化。
开始
基本使用
依赖
compile 'com.google.dagger:dagger:2.15'
annotationProcessor 'com.google.dagger:dagger-compiler:2.15'
先上代码
1 业务类。对构造函数进行声明标识,告诉Dagger。生成对象时可以使用这个构造方法。
public class UserService {
@Inject //(1)
UserService() {
}
//假设请求网络数据方法
public void request(){
}
}
2 还需要一个桥梁Component,和activity产生产生关系。
@Component
public interface MainComponent {
//说明要在那个activity注入
void inject(MainActivity mainActivity);
}
3.写好之后进行重构生成注入代码。
重构完后会生成一个DaggerMainComponent,提供注入,名字生成的规则是DaggerXXComponent。
最后在activity使用
public class MainActivity extends AppCompatActivity {
@Inject//(2)要new哪个业务类。就inject哪个。
UserService mUserService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//(3)注入
DaggerMainComponent.builder().build().inject(this);
Log.w(MainActivity.class.getSimpleName(),mUserService.toString());
mUserService.request();
}
}
说明一下这两个注解的意思:
@inject
对构造函数进行声明,Dagger可以构建该类的实例。//对应注释(1)
对字段,也就是成员变量声明,就是告诉dagger2 我需要这个实例对象。//对应注释(2)
@Component
- 可以理解为桥梁,就是将它们联系起来。
这样就完成一个对象最简单的注入。
接下来需求改变:Userservic 需要一个Gson对象和Context
public class UserService {
private Context context;
private Gson gson;
@Inject
public UserService(Gson gson, Context context){
this.gson = gson;
this.context = context;
}
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public Gson getGson() {
return gson;
}
public void setGson(Gson gson) {
this.gson = gson;
}
}
这时如果要实例化Gson,按照上面的步骤来说,应该在Gson的构造函数标识@inject。才可以被实例化,由于无法做到(因为第三方类不能修改),所以就只能声明Module仓库来提供Gson对象。
Module还可以通过构造函数去提供Context实例,并提供出去。
声明Module
@Module
public class UserModule {
Context mContext;
public UserModule(Context context) {
this.mContext = context;
}
@Provides
Context provideContext(){
return mContext;
}
@Provides
Gson providerGson(){
return new Gson();
}
@Provides
UserService providerUserService(Gson gson){
return new UserService(gson,mContext);
}
}
@Module
- 注解的类表明它可以提供依赖对象,声明这是一个仓库。标识可以提供对象
@Provides
- 告诉Dagger我们想要构造对象并提供这些依赖
修改Component,构建module的关系。
@Component(modules = UserModule.class)//可以有多个modules={xxxModule.class,XXclass,等等}
public interface MainComponent {
void inject(MainActivity mainActivity);
}
最后编译,activity调用
DaggerMainComponent.builder().userModule(new UserModule(this)).build().inject(this);
Dagger2的入门基本使用就到这里了,接下来项目阶段
先看一段代码
//UserModule:很简单就提供一个Gson
@Module
public class UserModule {
@Provides
Gson providerGson(){
return new Gson();
}
}
Component
@Component(modules = UserModule.class)
public interface MainComponent {
void inject(MainActivity mainActivity);
}
activity:注入2个Gson.
@Inject
Gson gson1;
@Inject
Gson gson2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainComponent.builder().userModule(new UserModule()).build().inject(this);
Log.w("MainActivity", Integer.toHexString(gson1.hashCode()));
Log.w("MainActivity", Integer.toHexString(gson2.hashCode()));
}
可以看到这是两个不同的对象
需求:单例
Dagger2:使用@Singleton标识 保持单例,也可以使用自定义scope或者使用Reusable。先说说@Singleton
@Provides
@Singleton
Gson provideGson() {
return new Gson();
}
@Singleton
@Component(modules = UserModule.class)
public interface MainComponent {
void inject(MainActivity mainActivity);
}
Activity不改,看看结果
@Singleton 注意事项:
通过这个标记,dagger2获取实例的方法会生成单例。
module提供对象的方法用@Singleton注解声明,其Component也要保持一致。不然会编译不通过。
除了上面要module和Component要使用同一个之外。想要要保证对象的全局单例,Component只能构建一次。
未完待续...