Android - Dagger2 使用和原理
Dagger2从入门到放弃再到恍然大悟
http://www.jianshu.com/p/cd2c1c9f68d4
http://www.jianshu.com/p/39d1df6c877d
http://blog.csdn.net/u012943767/article/details/51897247
源码解析:
DEMO
不依赖注入:
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) public interface MainComponent { void inject(MainActivity activity); }
分析
注入的目的就是两个:
1. 让view(Activity)得到 mainPresenter的依赖,可以调用它的方法
2. 让mainPresenter得到view(Activity)的依赖,可以调用它的方法
从源码看这两个目的实现
DaggerMainComponent.builder() .mainModule(new MainModule(this)) .build() .inject(this);
DaggerMainComponent.builder() 方法会实例化一个Build类并返回
Build类
Build类用来管理一个mainModule,并实例化DaggerMainComponent类。
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; } }
而mainModule负责管理一个view,别的类可以通过他的get()方法得到他管理的view(activity)。
@Module public class MainModule { private final MainContract.View mView; public MainModule(MainContract.View view) { mView = view; } @Provides MainContract.View provideMainView() { return mView; } }
所以这里
DaggerMainComponent.builder()
.mainModule(new MainModule(this))
就完成了把view(activity)依附到一个mainModule上,再实例化一个Build类管理mainModule,最后用这个Build来实例化DaggerMainComponent
而DaggerMainComponent用来管理三个成员
provideMainViewProvider : 如名字所说,管理着mainview,可以从中得到mainview
mainPresenterProvider: 如名字所说,管理着mainPresenter,可以从中得到mainPresenter
mainActivityMembersInjector:
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); } ... }
在Build的build()方法中创建了Dagger类的实例,从而调用了它的构造函数
DaggerMainComponent.builder()
.mainModule(new MainModule(this))
.build()
Dagger类的init()函数,首先用mainModule实例化了工厂类MainModule_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); } }
然后用provideMainViewProvider实例化了MainPresenter_Factory工厂类
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); } }
这个工厂类实例化了MainPresenter并返回,所以可以通过工厂类mainPresenterProvider的get方法得到mainPresenter。
public class MainPresenter { MainContract.View mView; @Inject MainPresenter(MainContract.View view) { mView = view; } }
在实例化
最后通过mainPresenterProvider实例化MainActivity_MembersInjector。我们看到这个类前面是MainActivity开头,因此可以想到是MainActivity对应得注入类,我们后面再分析这个类。
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(); } }
MainActivity_MembersInjector类持有一个MainPresenterProvider,从injectMembers方法可以让一个view(activity)得到这个mainPresenter。
另外MainPresenterProvider.get()方法实例化了MainPresenter
@Override public MainPresenter get() { return new MainPresenter(viewProvider.get()); }
public class MainPresenter { MainContract.View mView; @Inject MainPresenter(MainContract.View view) { mView = view; } }
至此MainPresenter就得到了View(Activity)的实例,可以调用它的方法,目的二实现
最后看
DaggerMainComponent.builder()
.mainModule(new MainModule(this))
.build()
.inject(this);
调用了Dagger的inject方法
@Override public void inject(MainActivity activity) { mainActivityMembersInjector.injectMembers(activity); }
就是上面的injectMembers方法。至此activity就拿到了mainPresenter的实例,可以调用它的方法
目的一实现。
感谢:
http://www.jianshu.com/p/cd2c1c9f68d4
http://alighters.com/blog/2016/04/15/dagger2-indepth-understanding/
http://chriszou.com/2016/05/10/android-unit-testing-di-dagger.html
http://blog.nimbledroid.com/2016/03/07/performance-of-dependency-injection-libraries-zh.html
http://google.github.io/dagger/
关于依赖的实现
这篇文章讲的不错,我的理解如下:
整个实现步骤大概是这样的
假设Bus类注入到MainActvitiy
1.编译生成BusProvider类,Injector类,以及一些工厂类
2.Dagger类初始化
调用BusProvider的create()函数得到BusProvider类的实例
如果create里需要busModule的provide参数则create(builder.busModule)
再调用Injector的create()得到Injector类实例
3.调用Injector的inject()方法,这个是在component里定义了inject给谁
Injector类持有注入对象的实例,inject(this)时传入的
@Override public void injectMembers(Bus instance) { if (instance == null) { throw new NullPointerException("Cannot inject members into a null reference"); } instance.engine = engineProvider.get(); }
调用了provider.get()方法
如果是构造函数,provider.get() 实现是 return new Bus();
如果是module,provider.get() 实现是 return module.provide();
- @Override
- public void injectMembers(Bus instance) {
- if (instance == null) {
- throw new NullPointerException("Cannot inject members into a null reference");
- }
- instance.engine = engineProvider.get();
- }