关于Dagger2是啥,用法网上已经有很多了。不过听说你已经很多次Dagger2从入门到放弃了,来来,让我这个老中医给你治一治。老夫手法纯熟,不会让你有任何痛苦的,放心读下去吧。

本文同步自 博主的私人博客 wing的地方酒馆

诊断

咳咳,看你这架势病的不清,应该是陌生代码恐惧症,你看看下面的代码。会不会害怕。

private ShipDetailPresenter mShipDetailPresenter;
mShipDetailPresenter = DaggerShipDetailComponent.builder()
.shipDetailModule(new ShipDetailModule(this, this))
.build()
.inject();

喂!!!你怎么跑了,快回来,还没治病呢!!

用法回顾(注入第一式)

首先,对于一般来说,想创建一个对象,我们肯定采取new的形式:

mShipDetailPresenter = new ShipDetailPresenter(context,shipDetailView);

但是这样耦合度较高,presenter的变化受限于Activity,也就是说假如我们的presenter的参数变成三个了,又要改Activity代码。所以使用Dagger2的好处就很明显了,如果改了构造器,只需要改对应的Module就可以。

@Module

上面提到了Module,这是什么呢?其实这是一个提供参数的地方,将new Presenter所需要的参数,写到这里面来了。看示例代码:

@Module //注解说明这是Module
public class ShipDetailModule {
private ShipDeatilContract.View mView;
private Context mContext; public ShipDetailModule(ShipDeatilContract.View mView, Context mContext) {
this.mView = mView;
this.mContext = mContext;
}
//注解说明Provide View 既提供View参数
@Provides ShipDeatilContract.View getView(){
return mView;
}
//注解说明Provide Context 既提供Context参数
@Provides Context getContext(){
return mContext;
}
}

这是Module的写法,就是把new Presenter(Context,View)写到了里面。

@Inject

Module怎么知道presenter构造器需要几个参数呢,答案是@Inject ,只需要在Presenter的构造器注解@Inject

public class ShipDetailPresenter implements ShipDeatilContract.Presenter {
Context context;
ShipDeatilContract.View shipDetailViewInterface;
//告知构造求所需参数
@Inject
public ShipDetailPresenter(Context context,ShipDeatilContract.View shipDetailViewInterface){
this.context=context;
this.shipDetailViewInterface=shipDetailViewInterface;
}

@Component

连接Presenter和Module的东东,我们只需要写一个接口,来返回Presenter对象,Dagger2就会自动生成对应的对象给我们。

//注解标注Component  并且告知需要的module是什么
@Component(modules = ShipDetailModule.class) public interface ShipDetailComponent {
//接口的方法,返回presenter
ShipDetailPresenter inject(); }

最终联系

现在看回第一段代码

   private ShipDetailPresenter mShipDetailPresenter;
mShipDetailPresenter = DaggerShipDetailComponent.builder()
.shipDetailModule(new ShipDetailModule(this, this))
.build()
.inject();

DaggerShipDetailComponent这个类是build之后Dagger2自动为我们生成的类,查看源码它实现了ShipDetialComponent这个方法,所以inject()函数自然会为我们返回一个presenter来啦。

用法回顾(注入第二式)

你可能犯嘀咕了,你这种写法不科学!跟我看到的不一样。咳咳,不要急,老夫再给你说另一种用法。这种方法的代码如下:

 @Inject ShipDetailPresenter mShipDetailPresenter;
DaggerShipDetailComponent.builder()
.shipDetailModule(new ShipDetailModule(this, this))
.build()
.inject(this);

对应的Component为:

public interface ShipDetailComponent {

  void inject(ShipDetailActivity);

}

其他的写法都一样。 此时你心里肯定犯嘀咕了,么么的,你刚才说是inject()返回presenter所以可以赋值,这个void你怎么解释! 是不是又要放弃拉,年轻人,不要轻言放弃,听老夫一言。

想要知道Dagger2 怎么做的那么神奇,必须知道他的原理,原理怎么看?当然是看他生成的代码呗!

Dagger2原理

第一式解密

首先看第一种方法的原理,找到DaggerShipDetailComponent 发现代码如下:

public final class DaggerShipDetailComponent implements ShipDetailComponent {
private Provider<Context> getContextProvider; private Provider<ShipDeatilContract.View> getViewProvider; private Provider<ShipDetailPresenter> shipDetailPresenterProvider;
/** 去处多行代码**/
}

可以看到Component确实实现了我们定义的Component,所以他的inject()方法肯定是返回了一个presenter

@Override
public ShipDetailPresenter inject() {
return shipDetailPresenterProvider.get();
}

老夫没有骗你吧,至于这个provider如何拿到的newPresenter,这里给你留个家庭作业。现在应该有些头绪了吧,Dagger2没有想象中那么难,对不对?接下来看看让你懵逼的第二式。

第二式

直接看生成的代码!在DaggerShipDetailComponent发现了

 public void inject(ShipDetailActivity activity) {
shipDetailsMembersInjector.injectMembers(activity);
}

继续往下看,看到了一个init方法

private void initialize(final Builder builder) {

    this.getContextProvider = ShipDetailModule_GetContextFactory.create(builder.shipDetailModule);

    this.getViewProvider = ShipDetailModule_GetViewFactory.create(builder.shipDetailModule);
//工厂生成provider 用来提供presenter
this.shipDetailPresenterProvider =
ShipDetailPresenter_Factory.create(getContextProvider, getViewProvider);
//生成MembersInjector
this.shipDetailActivityMembersInjector = ShipDetailActivity_MembersInjector.create(shipDetailPresenterProvider);
}

接下来顺藤摸瓜,找到了ShipDetailActivity_MembersInjector,只看关键部分源码


public final class ShipDetailActivity_MembersInjector
implements MembersInjector<ShipDetailActivity> { //进行注入操作
public static void injectShipDetailPresenter(
ShipDetailActivity instance, Provider<ShipDetailPresenter> shipDetailPresenterProvider) {
instance.shipDetailPresenter = shipDetailPresenterProvider.get();
}
}

相信聪明的你已经明白了,为什么返回void还能注入,不知道你有没有发现,第二式的presenter没有用private修饰,在injectShipDetailPresenter(ShipDetailActivity,Provider)的时候将 activity.presenter = Proivider.get()!

如果让我用两个字来形容的话,我只能说

太他妈精彩

嘛,这次会诊就到这里吧,回家记得勤加锻炼,早日康复,再见。

听说你又一次放弃了Dagger2,来听老夫说道说道的更多相关文章

  1. 掘金 Android 文章精选合集

    掘金 Android 文章精选合集 掘金官方 关注 2017.07.10 16:42* 字数 175276 阅读 50053评论 13喜欢 669 用两张图告诉你,为什么你的 App 会卡顿? - A ...

  2. ajax异步上传到又拍云的实例教程

    作者:白狼 出处:www.manks.top/article/async_upload_to_upyun 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否 ...

  3. [转载] TLS协议分析 与 现代加密通信协议设计

    https://blog.helong.info/blog/2015/09/06/tls-protocol-analysis-and-crypto-protocol-design/?from=time ...

  4. TLS协议分析

    TLS协议分析 本文目标: 学习鉴赏TLS协议的设计,透彻理解原理和重点细节 跟进一下密码学应用领域的历史和进展 整理现代加密通信协议设计的一般思路 本文有门槛,读者需要对现代密码学有清晰而系统的理解 ...

  5. 关于Dagger 2的文章汇总

    首先是我真正看懂了的第一篇文章 代码GG之家的 Dagger2图文详解 这篇文章很直接,还配有代码demo.至少我是看懂了. Dagger2 使用详解 这篇文章同样配有demo,同时文末还有很多有用的 ...

  6. PayPal高级工程总监:读完这100篇论文 就能成大数据高手(附论文下载)

    100 open source Big Data architecture papers for data professionals. 读完这100篇论文 就能成大数据高手 作者 白宁超 2016年 ...

  7. Asp.net 面向接口可扩展框架之核心容器(含测试代码下载)

    新框架的容器部分终于调通了!容器实在太重要了,所以有用了一个名词叫“核心容器”. 容器为什么那么重要呢?这个有必要好好说道说道. 1.首先我们从框架名称面向接口编程说起,什么是面向接口编程?(这个度娘 ...

  8. 算法系列:FFT 001

    转载自http://blog.csdn.net/orbit/article/details/17210461 2012年9月的时候,一个南京的大学生从电视台播放的一段记者采访360总裁周鸿祎的视频中破 ...

  9. redis入门笔记(2)

    redis入门笔记(2) 上篇文章介绍了redis的基本情况和支持的数据类型,本篇文章将介绍redis持久化.主从复制.简单的事务支持及发布订阅功能. 持久化 •redis是一个支持持久化的内存数据库 ...

随机推荐

  1. SQL_SERVER_2008升级SQL_SERVER_2008_R2的方法

    SQL 2008升级到SQL 2008 R2. 说到为什么要升级是因为,从另一台机器上备份了一个数据库,到我的机器上还原的时候提示"948错误,意思就是不能把高版本的数据库附加到低版本上,所 ...

  2. 浅谈Java中的equals和==与hashCode

    转载:https://www.cnblogs.com/dolphin0520/p/3592500.html 参考:http://blog.csdn.net/yinzhijiezhan/article/ ...

  3. Exchange Server 2010升级到Exchange Server 2016

    Hello各位小伙伴们,失踪人口回归啦~~~这次和大家分享Exchange Server 2010升级到Exchange Server 2016的方法.正式开始前先啰嗦几句,为什么我要写这篇文章呢?一 ...

  4. 阿里云部署Node.js项目(CentOS)

    Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,用来方便地搭建快速的易于扩展的网络应用.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又 ...

  5. 【已解决】IIS搭建 asp.net core 项目后 其他电脑访问不到资源文件

    IIS搭建asp.net core 项目后,访问不到里面的资源文件(图片等),解决方法如下: 1.检查asp.net core发布文件中的资源文件是不是都放到了wwwroot名称的目录中. 2.检查a ...

  6. 数据结构Java版之交换算法(一)

    交换的本质是拷贝,其中拷贝包括两种方式.值拷贝和指针拷贝,在java中没有指针,为此,我们可以理解为地址拷贝,在我看来,指针就是地址. 1.传值方式示例: 由上述示例可得,传值,不能起到交换的作用,原 ...

  7. Throughtput收集器

    介绍 JVM里面的Throughtput收集器是一款关注吞吐量的垃圾收集器.该收集器是唯一一个实现了UseAdaptiveSizePolicy策略的收集器,允许用户通过指定最大暂停时间和垃圾收集时间占 ...

  8. springMVC源码分析--ModelAndViewContainer和ModelMap

    ModelAndViewContainer主要是用来返回Model对象的,在ModelAndViewContainer中有defaultModel和redirectModel, defaultMode ...

  9. ejabberd为游戏免除注册限制

    ejabberd为游戏免除注册限制 (金庆的专栏 2016.11) ejabberd聊天服务器默认会限制同一IP注册帐号须间隔600s. 在游戏中需要为每个角色注册一个聊天帐号,不应该有此限制. 可以 ...

  10. Objective-C语法概述

    Objective-C语法概述 简称OC 面向对象的C语言 完全兼容C语言 可以在OC里面混入C/C++代码 可以开发IOS和Mac OS X平台应用 语法预览 关键字 基本上都是以@开头(为了与C语 ...