java注解除了解耦个人认为还有使代码简洁、逻辑更加突出业务逻辑代码、由于创建对象的集中,更加方便对象的维护与测试、对象的创建和生命周期的管控都交由框架等优点。
Dagger2的历史:
Dagger1是Square公司开发,Dagger2则由谷歌接收在dagger1的分支上开发而来,Dagger1用了反射,消耗了一些性能,Dagger2则被谷歌声称性能提高了13%,但是其灵活性减少
添加依赖:
implementation 'com.google.dagger:dagger:2.4'
annotationProcessor 'com.google.dagger:dagger-compiler:2.4'
创建一个实体类:
public class DaggerTestBean {
private String msg="DaggerTestBean注入成功了";
@Inject
public DaggerTestBean(){
}
public String showMessage(){
return msg;
}
}
在构造函数上添加@Inject注解
在需要依赖的类中生命对象:
public class DaggerTestActivity extends AppCompatActivity {
@Inject
DaggerTestBean mDaggerTestBean;
private TextView mTvDagger;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_daggertest);
mTvDagger = findViewById(R.id.tv_dagger);
DaggerMainComponent.builder().mainModule(new MainModule()).build().inject(this);
Log.d("daggerTest", "msg: " + mDaggerTestBean.showMessage());
}
}
并在声明的对象上添加@Inject注解,仅仅如此还不够
我们需要一个Module,和一个Component类
Module用来声明可以提供哪些实现,如下:
@Module
public class MainModule {
}
这里暂时用一个空的添加了@Module注解的Module类
Component是注解器,链接依赖方和Module,如下:
@Singleton
@Component(modules = MainModule.class)
public interface MainComponent {
void inject(DaggerTestActivity daggerTestActivity);
}
添加了@Singleton和@Component注解,并指定了modules为MainModule.class,这里是要指明该注入器依赖和被依赖的范围,
需要的模块都建立好了,最后在需要依赖的地方DaggerTestActivity的oncreate中添加注入动作代码:
DaggerMainComponent.builder().mainModule(new MainModule()).build().inject(this);
运行输出:
daggerTest: msg: DaggerTestBean注入成功了
这样简单的使用过程就完成了。
上边的例子是对Bean做了Inject处理,标识可被Module创建对象,也可以在Module中添加提供方法:
@Module
public class MainModule {
@Provides
DaggerTestBean provideTestBean(){
return new DaggerTestBean();
}
}
这样就不需要在Bean中添加Inject注解了。
看下编译器做了什么,打开app/build/generated/ap_generated_sources/debug/out/com/modeng/aspro/下多了
DaggerMainComponent.builder().mainModule(new MainModule()).build().inject(this);
追踪inject,发现逻辑还是挺清晰的,
DaggerMainComponent即为编译器自动生成的规则为Dagger+Component类名的类,看下其inject方法:
@Override
public void inject(DaggerTestActivity daggerTestActivity) {
daggerTestActivityMembersInjector.injectMembers(daggerTestActivity);
}
调用了daggerTestActivityMembersInjector的injectMenbers方法,看下这个daggerTestActivityMembersInjector对象是什么:
private void initialize(final Builder builder) {
this.daggerTestActivityMembersInjector =
DaggerTestActivity_MembersInjector.create(com.modeng.voicecontrolpro.utils.DaggerTestBean_Factory.create());
}
在DaggerMainComponent的initialize方法中创建,其就是编译器生成的DaggerTestActivity_MembersInjector类,看下其injectMembers方法:
@Override
public void injectMembers(DaggerTestActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.mDaggerTestBean = mDaggerTestBeanProvider.get();
}
这里有些熟悉的身影了,这里给DaggerTestActivity的mDaggerTestBean赋值了,mDaggerTestBean这个就是咱们添加注解需要注入的对象,继续看下mDaggerTestBeanProvider.get()
public DaggerTestActivity_MembersInjector(Provider<DaggerTestBean> mDaggerTestBeanProvider) {
assert mDaggerTestBeanProvider != null;
this.mDaggerTestBeanProvider = mDaggerTestBeanProvider;
}
DaggerTestActivity_MembersInjector在创建的时候给mDaggerTestBeanProvider赋值,继续跟踪
public static MembersInjector<DaggerTestActivity> create(
Provider<DaggerTestBean> mDaggerTestBeanProvider) {
return new DaggerTestActivity_MembersInjector(mDaggerTestBeanProvider);
}
来到了DaggerMainComponent类中:
private void initialize(final Builder builder) {
this.daggerTestActivityMembersInjector =
DaggerTestActivity_MembersInjector.create(com.modeng.voicecontrolpro.utils.DaggerTestBean_Factory.create());
}
继续看下DaggerTestBean_Factory的create方法,很明显这个是工厂方法:
creat方法拿到的是DaggerTestBean_Factory的实例,通过get方法,拿到创建好的DaggerTestBean对象,至此依赖对象和被依赖对象绑定,完成注入。
public enum DaggerTestBean_Factory implements Factory<DaggerTestBean> {
INSTANCE;
@Override
public DaggerTestBean get() {
return new DaggerTestBean();
}
public static Factory<DaggerTestBean> create() {
return INSTANCE;
}
}
上边讲的是基本用法了,现在来看下其它一些常用切比较复杂的场景:
public class DaggerTestBean {
private String msg="DaggerTestBean注入成功了,是测试环境";
public DaggerTestBean(){
}
public DaggerTestBean(String a){
this.msg = a;
}
public String showMessage(){
return msg;
}
}
@Module
public class MainModule {
@Named("debug")
@Provides
DaggerTestBean provideTestBean(){
return new DaggerTestBean();
}
@Named("release")
@Provides
DaggerTestBean provideTestBeanWithParams(){
return new DaggerTestBean("DaggerTestBean注入成功了,是生产环境");
}
}
public class DaggerTestActivity extends AppCompatActivity {
@Named("params")
@Inject
DaggerTestBean mDaggerTestBean;
添加一个Module:AMoudle
@Module
public class AModule {
@Named("debug")
@Provides
DaggerTestChildBean provideTestBean(){
return new DaggerTestChildBean();
}
@Named("release")
@Provides
DaggerTestChildBean provideTestBeanWithParams(){
return new DaggerTestChildBean("DaggerTestChildBean注入成功了,是生产环境");
}
}
提供的是DaggerTestChildBean:
public class DaggerTestChildBean {
private String msg="DaggerTestChildBean注入成功了,是测试环境";
public DaggerTestChildBean(){
}
public DaggerTestChildBean(String a){
this.msg = a;
}
public String showMessage(){
return msg;
}
}
当一个Component同时需要MainModule和AModule提供对象时可以有不同的方式:
Comopent注解中添加dependencies参数
@Singleton
@Component(modules = AModule.class,dependencies = MainModule.class)
public interface MainComponent {
void inject(DaggerTestActivity daggerTestActivity);
}
Module注解中添加include参数
@Module(includes = AModule.class)
public class MainModule {
@Named("debug")
@Provides
DaggerTestBean provideTestBean(){
return new DaggerTestBean();
}
@Named("release")
@Provides
DaggerTestBean provideTestBeanWithParams(){
return new DaggerTestBean("DaggerTestBean注入成功了,是生产环境");
}
}
Compoent注解中添加Module数组:
@Singleton
@Component(modules = {MainModule.class,AModule.class})
public interface MainComponent {
void inject(DaggerTestActivity daggerTestActivity);
}
这里要注意,单利是跟着被注入的对象的作用域走的,如果如果被注入到Activity中,作用域是Activity,换到其它Activity就重新创建对象了。
@Singleton
@Component(modules = MainModule.class)
public interface MainComponent {
void inject(DaggerTestActivity daggerTestActivity);
}
public class DaggerTestActivity extends AppCompatActivity {
@Named("release")
@Inject
DaggerTestBean mDaggerTestBean;
@Named("release")
@Inject
DaggerTestBean mDaggerTestBean1;
Log.d("daggerTest", "msg: mDaggerTestBean的hashCode = " + mDaggerTestBean.hashCode() + " mDaggerTestBean1的hashCode = " + mDaggerTestBean1.hashCode());
输出:daggerTest: msg: mDaggerTestBean的hashCode = 224228315 mDaggerTestBean1的hashCode = 224228315
如果定义在其它Activity:
分别输出:
daggerTest: msg: mDaggerTestBean的hashCode = 224228315 mDaggerTestBean1的hashCode = 224228315
daggerTest: msg: mDaggerTestBean的hashCode = 12558410 mDaggerTestBean1的hashCode = 12558410
既然单利跟着作用域走,那么在Application中的对象就应该是在整个app生命周期的单例了。
创建自定义Application,并创建MainCompoent对象:
public class MyApplication extends Application {
private MainComponent mainComponent;
@Override
public void onCreate() {
super.onCreate();
mainComponent = DaggerMainComponent.builder().mainModule(new MainModule()).build();
}
public MainComponent getMainComponent(){
return mainComponent;
}
}
在Activity中拿到MainComponent对象并注入:
((MyApplication) getApplication()).getMainComponent().inject(this);
public class DaggerTestActivity extends AppCompatActivity {
@Named("release")
@Inject
DaggerTestBean mDaggerTestBean;
@Named("release")
@Inject
DaggerTestBean mDaggerTestBean1;
public class DaggerTest1Activity extends AppCompatActivity {
@Named("release")
@Inject
DaggerTestBean mDaggerTestBean;
@Named("release")
@Inject
DaggerTestBean mDaggerTestBean1;
输出:
singleton: onCreate: mDaggerTestBean = 224228315 mDaggerTestBean1 = 224228315
singleton: onCreate: mDaggerTestBean = 224228315 mDaggerTestBean1 = 224228315
可以看到,两个activity的对象都是一样的。