转自http://www.jianshu.com/p/39d1df6c877d
博主讲的实在是好, 我简单记录一下, 方便自己的记忆.
(1)使用场景, 一个类需要使用另一个类作为成员的时候.
public class ClassA {
...
ClassB b;
...
public ClassA() {
b = new ClassB();
}
public void do() {
...
b.doSomething();
...
}
}
这个时候就产生了依赖问题,ClassA依赖于ClassB,必须借助ClassB的方法,才能完成一些功能。这样看好像并没有什么问题,但是我们在ClassA的构造方法里面直接创建了ClassB的实例,问题就出现在这,在ClassA里直接创建ClassB实例,违背了单一职责原则,ClassB实例的创建不应由ClassA来完成;其次耦合度增加,扩展性差,如果我们想在实例化ClassB的时候传入参数,那么不得不改动ClassA的构造方法,不符合开闭原则.
(2)使用Dragger2
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
//添加apt插件
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
apply plugin: 'com.android.application'
//添加如下代码,应用apt插件
apply plugin: 'com.neenbedankt.android-apt'
...
dependencies {
...
compile 'com.google.dagger:dagger:2.4'
apt 'com.google.dagger:dagger-compiler:2.4'
//java注解
compile 'org.glassfish:javax.annotation:10.0-b28'
...
}
(3)举个例子
-----------------------------------------------------------------------------------------------------
public class MainActivity extends AppCompatActivity implements MainContract.View {
private MainPresenter mainPresenter;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化presenter 将view传递给presenter
mainPresenter = new MainPresenter(this);
//调用Presenter方法加载数据
mainPresenter.loadData();
...
}
}
public class MainPresenter {
//MainContract是个接口,View是他的内部接口,这里看做View接口即可
private MainContract.View mView;
MainPresenter(MainContract.View view) {
mView = view;
}
public void loadData() {
//调用model层方法,加载数据
...
//回调方法成功时
mView.updateUI();
}
=============================================================================
使用依赖注入的话
-------------------------------------------------------------------------------------------------------------------------------
public class MainActivity extends AppCompatActivity implements MainContract.View {
@Inject
MainPresenter mainPresenter;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainComponent.builder()
.mainModule(new MainModule(this))
.build()
.inject(this);
//调用Presenter方法加载数据
mainPresenter.loadData();
...
}
}
public class MainPresenter {
//MainContract是个接口,View是他的内部接口,这里看做View接口即可
private MainContract.View mView;
@Inject
MainPresenter(MainContract.View view) {
mView = view;
}
public void loadData() {
//调用model层方法,加载数据
...
//回调方法成功时
mView.updateUI();
}
@Module//用来提供依赖
public class MainModule {
private final MainContract.View mView;
public MainModule(MainContract.View view) {
mView = view;
}
@Provides
MainView provideMainView() {
return mView;
}
}
@Component(modules = MainModule.class)//连接依赖与inject类的桥梁
public interface MainComponent {
void inject(MainActivity activity);
}
==============================================================================
(4)Drager2的注入过程分析
@Inject 带有此注解的属性或构造方法将参与到依赖注入中,Dagger2会实例化有此注解的类@Inject
MainPresenter mainPresenter; //实例化此类
@Module 带有此注解的类,用来提供依赖,里面定义一些用@Provides注解的以provide开头的方法,这些方法就是所提供的依赖,Dagger2会在该类中寻找实例化某个类(@inject)所需要的依赖。
@Component 用来将@Inject和@Module联系起来的桥梁,从@Module中获取依赖并将依赖注入给@Inject
DaggerMainComponent.builder()
.mainModule(new MainModule(this))//实例化module
.build()
.inject(this);//注入给inject类对象
(5)dragger2注入原理
它是通过apt插件在编译阶段生成相应的注入代码.MainPresenter的实例化过程。(见下面第一步)MainPresenter会对应的有一个工厂类,在这个类的get()方法中进行MainPresenter创建,(见下面第二步)而MainPresenter所需要的View依赖,是由MainModule里定义的以provide开头的方法所对应的工厂类提供的
<1>被@Inject的类, 在rebuild工程的时候, 会生成MainPresenter_Factory
在/app/build/generated/apt/debug/目录下.
主要功能:利用依赖的Provider(@Module标记的类), 生成被@inject标记的类.
-----------------------------------------------------------------------------------------------
public final class MainPresenter_Factory implements Factory<MainPresenter> {
private final Provider<MainContract.View> viewProvider;
public MainPresenter_Factory(Provider<MainContract.View> viewProvider) {
assert viewProvider != null;
this.viewProvider = viewProvider;
}
@Override
public MainPresenter get() {
return new MainPresenter(viewProvider.get());
}
public static Factory<MainPresenter> create(Provider<MainContract.View> viewProvider) {
return new MainPresenter_Factory(viewProvider);
}
}
===========================================================
<2>在MainModule中定义的@Provides修饰的方法会对应的生成一个工厂类,这里是MainModule_ProvideMainViewFactory, 上面的MainPresenter(viewProvider.get());
这个Provider, 就是ProvideMainViewFactory.用来提供依赖的.
---------------------------------------------------------------------------------------------------------------------
public final class MainModule_ProvideMainViewFactory implements Factory<MainContract.View> {
private final MainModule module;
public MainModule_ProvideMainViewFactory(MainModule module) {
assert module != null;
this.module = module;
}
@Override
public MainContract.View get() {
return Preconditions.checkNotNull(
module.provideMainView(), "Cannot return null from a non-@Nullable @Provides method");
}
public static Factory<MainContract.View> create(MainModule module) {
return new MainModule_ProvideMainViewFactory(module);
}
}
=========================================================================
<3>以上创建过程的发起人, DaggerMainComponent , @Module和@Inject的桥梁
他的主要作用.
根据调用流程, 逐步分析源码:
DaggerMainComponent.builder()
.mainModule(new MainModule(this))//实例化module
.build()
.inject(this);//将生成的@Inject对象, 送给MainActivity.
I.根据我们自己写的MainModule(可以get到activity实现的 MainContract.View).创建MainModule_ProvideMainViewFactory.
II.根据MainModule_ProvideMainViewFactory(实际继承自Provider),
创建MainPresenter_Factory
III.根据MainPresenter_Factory创建MembersInjector<MainActivity>
IV. MainActivity_MembersInjector里面会获取@Inject的真正实例, 就完成创建了.
MainActivity_MembersInjector里的关键代码injectMembers(MainActivity.this), 会把@inject实例, 传递给injectMembers的参数(MainActivity. mainPresenter)
--------------------------------------------------------------------------------------------------------------------
public final class DaggerMainComponent implements MainComponent {
private Provider<MainContract.View> provideMainViewProvider;
private Provider<MainPresenter> mainPresenterProvider;
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 = MainModule_ProvideMainViewFactory.create(builder.mainModule);
this.mainPresenterProvider = MainPresenter_Factory.create(provideMainViewProvider);
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(mainPresenterProvider);
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
public static final class Builder {
private MainModule mainModule;
private Builder() {}
public MainComponent build() {
if (mainModule == null) {
throw new IllegalStateException(MainModule.class.getCanonicalName() + " must be set");
}
return new DaggerMainComponent(this);
}
public Builder mainModule(MainModule mainModule) {
this.mainModule = Preconditions.checkNotNull(mainModule);
return this;
}
}
}
=======================================================================
----------------------------------------------------------------------------------------------------------------------
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<MainPresenter> mainPresenterProvider;
public MainActivity_MembersInjector(Provider<MainPresenter> mainPresenterProvider) {
assert mainPresenterProvider != null;
this.mainPresenterProvider = mainPresenterProvider;
}
public static MembersInjector<MainActivity> create(
Provider<MainPresenter> mainPresenterProvider) {
return new MainActivity_MembersInjector(mainPresenterProvider);
}
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.mainPresenter = mainPresenterProvider.get();
}
public static void injectMainPresenter(
MainActivity instance, Provider<MainPresenter> mainPresenterProvider) {
instance.mainPresenter = mainPresenterProvider.get();
}
}
=========================================================================