Java作为面向对象的编程语言,较低耦合度无疑可以提高代码的复用和维护;
今天来介绍一个依赖动态注入解耦的神奇dagger2(最常用的场景mvp+rxjava+dagger2)
1.dagger2–简单介绍
首先dagger2是利用apt变成在rebuild时候 相应注解类生成对应的factory工厂类来实现动态注射;
在dagger2中核心就是注解:
@Inject:动态注入 多用于成员的初始化
@Module:对于一些没有构造或者取不到构造的可以选择通过这个注解下的类获取相关的属性(说的比较委婉 没事 一会会有注解的源码分析)
@Component:桥梁;是核心注解类的工厂类的实例化类
…..还有一些注解 暂时不做解释 有兴趣可以自行查看文档 对于没有接触过dagger2的程序员会有陌生感 但是习惯了 就会觉得蛮好用 解耦效果好 对后期项目维护和迭代修改有很大的便利
2.代码实现dagger2
首先添加依赖 //在app –build.gradle
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
.......
dependencies {
......
......
compile 'com.google.dagger:dagger:2.4'
apt 'com.google.dagger:dagger-compiler:2.4'
compile 'org.glassfish:javax.annotation:10.0-b28'// 添加java 注解库
//在项目—build.gradle
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
//配置Android annotations
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
由于是由dagger2要使用apt编程所以需要在项目的build.gradle中添加插件的依赖(详细请看上面的代码)
代码中分为dagger2的utils类 即dagger2的核心注解类+业务逻辑类+View的UI
比较简单,贵在体会dagger2的妙用
2.1 dagger核心工具类:
首先穿件module类:
@Module
public class ActivityModule {
private MainActivity mView;
public ActivityModule(MainActivity view) {
mView = view;
}
@Provides
public MainActivity provideMainView(){
return mView;
}
}
构造中参数是MainActivity 然后提供一个get一样的类返回MainActivity的对象,需要注意的一点,返回实例的类被注解@Provides修饰,而且类名必须为providexxx;这个类通过接收参数会返回MainActivity的对象
然后看Component类:
@Component(modules = ActivityModule.class)
public interface MainComponent {
void inject(MainActivity activity);
}
2.2.presenter
//
public class FirstPresenter {
private MainActivity mView;
@Inject
public FirstPresenter(MainActivity view) {
this.mView = view;
}
public String showStr(){
return "hello_dagger2_调用";
}
}
2.3 最后看Activity:
public class MainActivity extends AppCompatActivity {
@Inject
FirstPresenter mPresenter;
private TextView mTv;
private Button mBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv = (TextView) findViewById(R.id.tv_content);
mBtn = (Button) findViewById(R.id.btn_call);
// 构造桥梁对象
DaggerMainComponent.builder()
.activityModule(new ActivityModule(this))
.build()
.inject(this);
mBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String showStr = mPresenter.showStr();
mTv.setText(showStr);
}
});
}
}
核心代码:
public class MainActivity extends AppCompatActivity {
@Inject
FirstPresenter mPresenter;
....
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
.......
// 构造桥梁对象
DaggerMainComponent.builder()
.activityModule(new ActivityModule(this))
.build()
.inject(this);
......
});
}
}
首先:
@Inject FirstPresenter mPresenter;
由于FirstPresenter的构造被@Inject修饰 这句相当于初始化成员变量mPresenter
然后:
DaggerMainComponent.builder()
.activityModule(new ActivityModule(this))
.build()
.inject(this);
在dagger2的注解类rebuild之后会在build/generated/source/apt/debug下回生成相对应的注解类;(DaggerMainComponent就是MainComponent对应的注解类)—–>builder()启动每一个Factory的creact方法——->activityModule(new ActivityModule(this))是走Activity的构造,然后返回MainActivity的实例—–>.inject(this);返回的参数传入FirstPresenter 得到其对象 可以看出来 一个很简单的操作辗转了好几次,或许会有不解,但是如果你和一个有经验的开发人员你会发现这样解耦好处颇多;
3.对比工厂类来探究原理:
首先来看管理所有注解工厂类实例化的工厂类: //MainComponent
@Component(modules = ActivityModule.class)
public interface MainComponent {
void inject(MainActivity activity);
}
//工厂类
public final class DaggerMainComponent implements MainComponent {
private Provider<MainActivity> provideMainViewProvider;
private Provider<FirstPresenter> firstPresenterProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
private DaggerMainComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.provideMainViewProvider =
ActivityModule_ProvideMainViewFactory.create(builder.activityModule);
this.firstPresenterProvider = FirstPresenter_Factory.create(provideMainViewProvider);
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(firstPresenterProvider);
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
public static final class Builder {
private ActivityModule activityModule;
private Builder() {}
public MainComponent build() {
if (activityModule == null) {
throw new IllegalStateException(ActivityModule.class.getCanonicalName() + " must be set");
}
return new DaggerMainComponent(this);
}
public Builder activityModule(ActivityModule activityModule) {
this.activityModule = Preconditions.checkNotNull(activityModule);
return this;
}
}
}
在以上代码中:
private void initialize(final Builder builder) {
this.provideMainViewProvider =
ActivityModule_ProvideMainViewFactory.create(builder.activityModule);
this.firstPresenterProvider = FirstPresenter_Factory.create(provideMainViewProvider);
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(firstPresenterProvider);
}
通过initialize创建了除本类外所有的注解工厂类 这工厂类内部使用构造模式 来实例化本类
//FirstPresenter
public class FirstPresenter {
private MainActivity mView;
@Inject
public FirstPresenter(MainActivity view) {
this.mView = view;
}
public String showStr(){
return "hello_dagger2_调用";
}
}
//工厂类
public final class FirstPresenter_Factory implements Factory<FirstPresenter> {
private final Provider<MainActivity> viewProvider;
public FirstPresenter_Factory(Provider<MainActivity> viewProvider) {
assert viewProvider != null;
this.viewProvider = viewProvider;
}
@Override
public FirstPresenter get() {
return new FirstPresenter(viewProvider.get());
}
public static Factory<FirstPresenter> create(Provider<MainActivity> viewProvider) {
return new FirstPresenter_Factory(viewProvider);
}
}
首先是viewProvider是Provider(泛型:MainActivity),考虑一下,其实viewProvide就是ActivityModule对象,至于viewProvider.get()就是ActivityModule中返回MainActivity的实例 所以FirstPresenter的实例化要依赖于ActivityModule;
那么接下来看ActivityModule的工厂类:
//ActivityModule
@Module
public class ActivityModule {
private MainActivity mView;
public ActivityModule(MainActivity view) {
mView = view;
}
@Provides
public MainActivity provideMainView(){
return mView;
}
}
//工厂类
public final class ActivityModule_ProvideMainViewFactory implements Factory<MainActivity> {
private final ActivityModule module;
public ActivityModule_ProvideMainViewFactory(ActivityModule module) {
assert module != null;
this.module = module;
}
@Override
public MainActivity get() {
return Preconditions.checkNotNull(
module.provideMainView(), "Cannot return null from a non-@Nullable @Provides method");
}
public static Factory<MainActivity> create(ActivityModule module) {
return new ActivityModule_ProvideMainViewFactory(module);
}
}
这样就简单了 ActivityModule的工厂类通过get返回MainActivity传给FirstPresenter的注解工厂类不就可以了么~
那么我们再来看MainActivty中核心代码:
DaggerMainComponent.builder()
.activityModule(new ActivityModule(this))
.build()
.inject(this);
首先 DaggerMainComponent.builder()创建builder对象 然后 最终通过build()实例化和创建所有的工厂类;并且通过.activityModule(new ActivityModule(this))传入activity来获取MainActivity的实例化对象;
最后关键的一步.inject(this);:
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
来看其中的注解工厂类:
)
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<FirstPresenter> mPresenterProvider;
public MainActivity_MembersInjector(Provider<FirstPresenter> mPresenterProvider) {
assert mPresenterProvider != null;
this.mPresenterProvider = mPresenterProvider;
}
public static MembersInjector<MainActivity> create(Provider<FirstPresenter> mPresenterProvider) {
return new MainActivity_MembersInjector(mPresenterProvider);
}
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.mPresenter = mPresenterProvider.get();
}
public static void injectMPresenter(
MainActivity instance, Provider<FirstPresenter> mPresenterProvider) {
instance.mPresenter = mPresenterProvider.get();
}
}
来看核心代码
instance.mPresenter = mPresenterProvider.get();
通过在ActivityModule中获取的MainActivity实例然后走FirstPresenter构造——>然后在这里调用instance.mPresenter = mPresenterProvider.get();—–>获取FirstPresenter ~ 大工告成
感谢阅读~ 希望多提建议 一同进步