Dagger2的原理

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





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值