Dragger2的原理

来源:互联网 发布:app的运营数据分析 编辑:程序博客网 时间:2024/06/03 23:40

转自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();  }}=========================================================================





原创粉丝点击