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/

关于依赖的实现

Dagger2的使用以及源码分析

这篇文章讲的不错,我的理解如下:

整个实现步骤大概是这样的

假设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();

  1. @Override
  2. public void injectMembers(Bus instance) {
  3. if (instance == null) {
  4. throw new NullPointerException("Cannot inject members into a null reference");
  5. }
  6. instance.engine = engineProvider.get();
  7. }

Android - Dagger2 使用和原理的更多相关文章

  1. (转)Android 系统 root 破解原理分析

    现在Android系统的root破解基本上成为大家的必备技能!网上也有很多中一键破解的软件,使root破解越来越容易.但是你思考过root破解的 原理吗?root破解的本质是什么呢?难道是利用了Lin ...

  2. Android系统Recovery工作原理

    Android系统Recovery工作原理之使用update.zip升级过程分析(一)---update.zip包的制作 http://blog.csdn.net/mu0206mu/article/d ...

  3. Android启动篇 — init原理(二)

    ========================================================          ================================== ...

  4. Android启动篇 — init原理(一)

    ========================================================          ================================== ...

  5. Android热修复技术原理详解(最新最全版本)

    本文框架 什么是热修复? 热修复框架分类 技术原理及特点 Tinker框架解析 各框架对比图 总结   通过阅读本文,你会对热修复技术有更深的认知,本文会列出各类框架的优缺点以及技术原理,文章末尾简单 ...

  6. Android FoldingLayout 折叠布局 原理及实现(二)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/44283093,本文出自:[张鸿洋的博客] 1.概述 在上一篇Android Fo ...

  7. Android 长截屏原理

    https://android-notes.github.io/2016/12/03/android%E9%95%BF%E6%88%AA%E5%B1%8F%E5%8E%9F%E7%90%86/   a ...

  8. Android 系统 root 破解原理分析 (续)

    上文<Android系统root破解原理分析>介绍了Android系统root破解之后,应用程序获得root权限的原理.有一些网友提出对于root破解过程比较感兴趣,也提出了疑问.本文将会 ...

  9. Android自复制传播APP原理学习(翻译)

     Android自复制传播APP原理学习(翻译) 1 背景介绍 论文链接:http://arxiv.org/abs/1511.00444 项目地址:https://github.com/Tribler ...

随机推荐

  1. DOM LEVEL 1 中的那些事儿[总结篇-下]

    本文承接:DOM LEVEL 1 中的那些事儿[上]   2.3 Element类型 Element类型应该是Document类型之外使用的最多的节点类型了,Element代表XML或HTML文档中的 ...

  2. @JsonInclude、@JsonFormat、@DateTimeFormat注解的使用

    @JsonInclude(value=Include.NON_NULL) :用在实体类的方法类的头上  作用是实体类的参数查询到的为null的不显示 @DateTimeFormat:用于接收 前端传的 ...

  3. centos7上编译安装mysql5.6

    注意,在做实验室统一关闭防火墙做的,在生产环境需要做防火墙规则的,大家要注意,做的时候尽量都是模仿生产环境的,比如服务一般都在/data/soft下面,尽量避免在/usr/local/下面. 安装编译 ...

  4. python学习笔记10-文件操作

    能调用方法的一定是对象.文件本身也是一个对象.有很多自己内置的方法 #操作文件第一件事 建立文件对象 open函数 # 参数一:文件路径 绝对路径和相对路径都可以 # 参数二:模式选择 ‘r’ 读模式 ...

  5. [翻译] Trident-ML:基于storm的实时在线机器学习库

    最近在看一些在线机器学习的东西,看到了trident-ml, 觉得比较有意思,就翻译了一下,方便有兴趣的读者学习. 本文为作者(掰棒子熊)翻译自https://github.com/pmerienne ...

  6. nginx lua集成

    版本说明: linux: 1.8.1 luajit:2.0.2(不要使用标准lua,应当使用luajit, 后者的效率比前者高很多) ngx_devel_kit: 0.2.18 lua-nginx-m ...

  7. Nginx 配置 Location 规则优先级问题

    nginx 的 location与配置中 location 顺序没有关系,与 location 表达式的类型有关.相同类型的表达式,字符串长的会优先匹配. 以下是按优先级排列说明: 等号类型(=)的优 ...

  8. CentOS 7.5 安装与配置 Percona Server 5.7

    个人比较喜欢 MYSQL 的轻量,今天花了一点时间把阿里云上的 MYSQL5.7 换成了 Percona-Server .Percona 是一个开源的 MySQL 衍生版,TokuDB 的数据库引擎使 ...

  9. Python做int()强制类型转换的时候,小数是如何取舍的?

    白月黑羽今天给大家分享一个冷知识:) int()强制类型转换小数是如何取舍的? 使用 int() 将小数转换为整数,小数取整会采用比较暴力的截断方式,即小数点后面的会被强制舍去,向下取整. 例如:5. ...

  10. Tensorflow运用RNN注意事项

    一.学习单步的RNN:RNNCell 如果要学习TensorFlow中的RNN,第一站应该就是去了解“RNNCell”,它是TensorFlow中实现RNN的基本单元,每个RNNCell都有一个cal ...