dagger2 循序渐进学习(包会)(二)

文章索引
dagger2 循序渐进学习(一)依赖注入基础知识(包会)
dagger2 循序渐进学习(二)
dagger2 循序渐进学习(三) 实例1,application中的应用

昨天写了关于dagger2 的重要但比较易于理解的基础知识 依赖注入,这里是链接dagger2 循序渐进学习(一)依赖注入基础知识
今天这篇就开始主要讲dagger2 本身了,遵循循序渐进简单易懂的原则,所以要花费一定篇幅。

那么首先要明确了解一下dagger2是什么:
Dagger1
这个版本不是这篇文章的重点,所以我只是简略地说一下。不管怎样,Dagger1还是做了很多的贡献,可以说是如今Android上最流行的依赖注入框架。它是由Square公司受到Guice启发创建的。
基本特点:
多个注入点:依赖,通过injected
多种绑定方法:依赖,通过provided
多个modules:实现某种功能的绑定集合
多个对象图: 实现一个范围的modules集合

Dagger1是在编译的时候实行绑定,不过也用到了反射机制。但这个反射不是用来实例化对象的,而是用于图的构成。Dagger会在运行的时候去检测是否一切都正常工作,所以使用的时候会付出一些代价:偶尔会无效和调试困难。
Dagger2
Dagger2是Dagger1的分支,由谷歌公司接手开发,目前的版本是2.0。Dagger2是受到AutoValue项目的启发。 刚开始,Dagger2解决问题的基本思想是:利用生成和写的代码混合达到看似所有的产生和提供依赖的代码都是手写的样子。
如果我们将Dagger2和1比较,他们两个在很多方面都非常相似,但也有很重要的区别,如下:
再也没有使用反射:图的验证、配置和预先设置都在编译的时候执行。
容易调试和可跟踪:完全具体地调用提供和创建的堆栈
更好的性能:谷歌声称他们提高了13%的处理性能
代码混淆:使用派遣方法,就如同自己写的代码一样

当然所有这些很棒的特点都需要付出一个代价,那就是缺乏灵活性,例如:Dagger2没用反射所以没有动态机制。

是不是蒙蔽了😓!!
废话少说,上代码,来看下如何找Android 中使用dagger2。
首先在整个项目的gradle文件中加入即时编译生成代码的apt插件依赖(或者也可以写到下面moudel的gradle文件中)

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'//这里是添加的,也可以写到下面moudel的gradle文件中
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

然后在moudel的gradle文件中加入相关依赖:

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt' //加入即时编译插件apt
android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "zhangzhe.daggerdemo"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.1.0'
    testCompile 'junit:junit:4.12'

    apt 'com.google.dagger:dagger-compiler:2.0'//这里是添加的
    compile 'com.google.dagger:dagger:2.0'//这里是添加的
    provided 'javax.annotation:jsr250-api:1.0'//这里是添加的
}

先不讲dagger2的理论一些名称直接撸代码;
以Android当前流行的mvp模式为例,写一个简要的登录demo。

1.先建立登录的activity 作为view层;

public class LoginActivity extends AppCompatActivity  {
 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
  
}
}

2.建立ILoginContract协议接口,定义view层和presenter层的逻辑。

public interface ILoginContract {
interface ILoginPresenter {
    void login(String name,String pwd);
}

interface ILoginView<ILoginPresenter>{
    void loginok();
    void loginErro();
}

}

3.建立presenter的实现类

public class LoginPresenter implements     ILoginContract.ILoginPresenter {
ILoginContract.ILoginView view;


public LoginPresenter(ILoginContract.ILoginView view) {
    this.view = view;
}

@Override
public void login(String name, String pwd) {

}
}

我们按常规的方式会把LoginPresenter 在activity中声明成员变量,并new 出来如下:

 public class LoginActivity extends AppCompatActivity  implements ILoginContract.ILoginView{
    
   LoginPresenter  presenter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
       presenter = new LoginPresenter(this);//这里有问题
    }

    @Override
    public void loginok() {

    }

    @Override
    public void loginErro() {

    }
}

如上,这里的presenter是new出来的,达到互相依赖的关系,这样就把彼此仅仅的耦合在一起了,一旦presenter的构造方法改变就要同时改变activity中的代码,这不是我们想要的。
那么dagger2 是如何注入的呢;
首先我们需要新建两个类文件:
Moudule类

@Module
public class LoginMoudule {
private final ILoginContract.ILoginView view;
public LoginMoudule(ILoginContract.ILoginView view) {
    this.view = view;
}
@Provides
ILoginContract.ILoginView provideLoginView(){
    return view;
}
}

Component类

@Component(modules = LoginMoudule.class)
public interface LoginComponent {
 void inject(LoginActivity activity);
}

可见moudule类用@Module 注解,构造方法中注入view层, 并用@Provides注解一个返回ILoginView的方法;Component类用@Component(modules = LoginMoudule.class)注解可见Component与LoginMoudule.class必然存在某种关系,并inject方法把activity联系起来,这样这几个类就肯定通过某种方法联系起来了,但这些联系并不需要我们程序员去写什么了。

接下来就是对view和presenter两个类内部进行改造:activity

public class LoginActivity extends AppCompatActivity  implements ILoginContract.ILoginView{
    @Inject//这里加注解
    LoginPresenter presenter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
    }

    @Override
    public void loginok() {

    }

    @Override
    public void loginErro() {

    }
}

presenter类

public class LoginPresenter implements ILoginContract.ILoginPresenter {
ILoginContract.ILoginView view;

@Inject//这里注解
public LoginPresenter(ILoginContract.ILoginView view) {
    this.view = view;
}

@Override
public void login(String name, String pwd) {
}
}

在activity中的依赖的presenter添加@Inject注解,同时在presenter中的构造方法同时加这个@Inject的注解,之后build一下整个项目,在项目的project视图下的build的文件夹下生成了如下的几个类,这就是dagger2 通过apt生成的辅助类,也是dagger2的玄机所在。

Paste_Image.png

回到activity中:

public class LoginActivity extends AppCompatActivity  implements ILoginContract.ILoginView{
    @Inject
    ILoginContract.ILoginPresenter presenter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
//添加此句
        DaggerLoginComponent.builder().loginMoudule(new LoginMoudule(this)).build().inject(this);
    }

    @Override
    public void loginok() {

    }

    @Override
    public void loginErro() {

    }
}

dagger2生成的义Dagger前缀的Component内部完成了这一系列注入过程。
到此为止mvp中v和p的互相注入通过dagger2已经完成,此时可以测试一下,看presenter是否会报空指针。你可能会说了,wtf(what the fuck)这么麻烦!!呵呵,和我一开始一样的。但是想想框架不一定就是能满足程序员的懒,框架麻烦但是能让我们的程序更健壮,或者维护起来会省很多事啊!想你说的 ,懒!没办法。
好今天就到这里,接下来会详细介绍dagger2 的细节,每天学一点点,厚积薄发。

每天发的东西都是我正在学习的东西,学习的同时,与更多人分享,一能增进我的记忆,同时提出自己的见解与大家互相促进提高,同时也希望收到拍砖

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容