Dagger2的使用

Dagger2 使用详解


前言

Dagger2 是一款使用在Java和Android上的依赖注入的一个类库。

配置信息

使用Android Studio 创建一个新的项目,在Project的 build.gradle文件添加以下内容:

1234567
buildscript {

    dependencies {        classpath ‘me.tatarka:gradle-retrolambda:3.2.4‘        classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8‘    }}

并在Module下的build.gradle添加以下内容:

123456789101112131415
apply plugin: ‘com.neenbedankt.android-apt‘apply plugin: ‘me.tatarka.retrolambda‘

android {    compileOptions {        sourceCompatibility JavaVersion.VERSION_1_8        targetCompatibility JavaVersion.VERSION_1_8    }}

dependencies {    apt ‘com.google.dagger:dagger-compiler:2.4‘    compile ‘com.google.dagger:dagger:2.4‘    provided ‘org.glassfish:javax.annotation:10.0-b28‘}

这样就基本完全了Dagger2的配置环境(顺便也配置了支持lambda表达式)。

Dagger2基本使用

我们先简单地创建一个类:

12345678910111213
public class Poetry {    private String mPemo;

    // 用Inject标记构造函数,表示用它来注入到目标对象中去    @Inject    public Poetry() {        mPemo = "生活就像海洋";    }

    public String getPemo() {        return mPemo;    }}

然后我们在MainActivity中使用这个类:

123456789101112131415161718192021
public class MainActivity extends AppCompatActivity {

    //添加@Inject注解,表示这个mPoetry是需要注入的    @Inject    Poetry mPoetry;

    private TextView mTextView;

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

        initView();    }

    private void initView() {        mTextView = (TextView) findViewById(R.id.tv_poetry);        mTextView.setText(mPoetry.getPoems());    }}

但是这样直接运行是会出错的,此时这样子在MainActivity中的mPoetry对象是无法被注入的,因为MainActivity不知道去哪里找到它的实例去注入生成,这时我们需要一个连接器Component,让上面这两个类产生联系:

12345678910111213
//用@Component表示这个接口是一个连接器,能用@Component注解的只//能是interface或者抽象类@Componentpublic interface MainComponent {

    /**     * 需要用到这个连接器的对象,就是这个对象里面有需要注入的属性     * (被标记为@Inject的属性)     * 这里inject表示注入的意思,这个方法名可以随意更改,但建议就     * 用inject即可。     */    void inject(MainActivity activity);}

先运行一遍,AS会生成一些类,再修改一下MainActivity:

1234567891011121314151617181920212223242526
public class MainActivity extends AppCompatActivity {

    //添加@Inject注解,表示这个mPoetry是需要注入的    @Inject    Poetry mPoetry;

    private TextView mTextView;

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

        // 使用Dagger2生成的类 生成组件进行构造,并注入        DaggerMainComponent.builder()                .build()                .inject(this);

        initView();    }

    private void initView() {        mTextView = (TextView) findViewById(R.id.tv_poetry);        mTextView.setText(mPoetry.getPoems());    }}

运行,如下

上面MainActivity中的Poetry实例并不直接由MainActivity类创建,而是由MainActivityComponent类注入生成实例。以上就是一个简单的Dagger2示例。

@Module

有时候我们并不能直接在构造函数里面添加@Inject注解,或者类中存在多个构造函数时,@Inject也只能注解其中一个构造函数,不能注解多个构造函数,这里是会产生歧义性,因为Dagger2无法确认调用哪一个构造函数来生成例的实例对象。另外一种情况是我们在项目中引用第三方类库时,也是无法直接在类构造函数中添加@Inject注解的,所以我们需要用到@Module注解了。
@Module是用来生产实例来注入对象的,它类似一个工厂,集中创建要注入的类的对象实例。下面我们引用一下Gson库来看看@Module是怎么使用的,创建MainModule类:

12345678910111213141516
/*@Module注解表示这个类提供生成一些实例用于注入 */@Modulepublic class MainModule {

    /**     * @Provides 注解表示这个方法是用来创建某个实例对象的,这里我们创建返回Gson对象     * 方法名随便,一般用provideXXX结构     * @return 返回注入对象     */    @Provides    public Gson provideGson(){        return new Gson();    }}

添加完这个类后,我们要与之前写的类产生关联,不然谁知道你这里提供了生成Gson实例的方法啊。修改MainCompontent:

123456789101112
//这里表示Component会从MainModule类中拿那些用@Provides注解的方法来生成需要注入的实例@Component(modules = MainModule.class)public interface MainComponent {

    /**     * 需要用到这个连接器的对象,就是这个对象里面有需要注入的属性     * (被标记为@Inject的属性)     * 这里inject表示注入的意思,这个方法名可以随意更改,但建议就     * 用inject即可。     */    void inject(MainActivity activity);}

这里多了一个依赖,依赖MainModule类中的方法生成Gson实例,我们在MainActivity里注入Gson实例:

123456789101112131415161718192021222324252627282930
public class MainActivity extends AppCompatActivity {

    //添加@Inject注解,表示这个mPoetry是需要注入的    @Inject    Poetry mPoetry;

    @Inject    Gson mGson;

    private TextView mTextView;

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

        // 使用Dagger2生成的类 生成组件进行构造,并注入        DaggerMainComponent.builder()                .build()                .inject(this);

        initView();    }

    private void initView() {        mTextView = (TextView) findViewById(R.id.tv_poetry);        String json = mGson.toJson(mPoetry);        mTextView.setText(json);    }}

运行,结果如下:

Component可以依赖多个Module对象,以上的构造方法与生成方法都是无参生成实例的,如果我们带参数应该怎么做了?我们创建多一个PoetryModule用于提供Poetry实例:

1234567891011121314151617
@Modulepublic class PoetryModule {

    // 这个方法需要一个String参数,在Dagger2注入中,这些参数也是注入形式的,也就是    // 要有其他对方提供参数poems的生成,不然会造成编译出错    @Provides    public Poetry providePoetry(String poems){        return new Poetry(poems);    }

    // 这里提供了一个生成String的方法,在这个Module里生成Poetry实例时,会查找到这里    // 可以为上面提供String类型的参数    @Provides    public String providePoems(){        return "只有意志坚强的人,才能到达彼岸";    }}

修改MainComponent依赖:

123456789101112
//这里表示Component会从MainModule类中拿那些用@Provides注解的方法来生成需要注入的实例@Component(modules = {MainModule.class,PoetryModule.class})public interface MainComponent {

    /**     * 需要用到这个连接器的对象,就是这个对象里面有需要注入的属性     * (被标记为@Inject的属性)     * 这里inject表示注入的意思,这个方法名可以随意更改,但建议就     * 用inject即可。     */    void inject(MainActivity activity);}

运行,就可以看到不同的诗词了:

细心的同学就会发现了,我们提供了两个可以生成Poetry实例的方法,一个是在Poetry类的构造函数时候用@Inject提供的实例创建方法,一个是在PoetryModule中的@Privodes注解的providePoetry方法,而在上面的运行结果中我们发现是调用了PoetryModule提供的方法,这里就要说明一下优先级的问题,在上面这种既在构造函数中用@Inject提供注入来源,也在@Module中用@Privodes注解提供注入来源的,Dagger2是先从@Privodes查找类实例,如果找到了就用@Module提供的方法来创建类实例,如果没有就从构造函数里用@Inject注解的生成类实例,如果二者都没有,则报错,简而言之,就是@Module的优先级高于@Inject
另外这里还要说明一点,在providePoetry(String)方法中,String这个参数也是要注入提供的,必须也要有在同一个连接器里面有提供,其中在构建类实例的时候,会按照以下顺序执行:

  1. 从Module中查找类实例创建方法
  2. Module中存在创建方法,则看此创建方法有没有参数
    1. 如果有参数,这些参数也是由Component提供的,返回步骤1逐一生成参数类实例,最后再生成最终类实例
    2. 如果无参数,则直接由这个方法生成最终类实例
  3. Module中没有创建方法,则从构造函数里面找那个用@Inject注解的构造函数
    1. 如果该构造函数有参数,则也是返回到步骤1逐一生成参数类实例,最后调用该构造函数生成类实例
    2. 如果该构造函数无参数,则直接调用该构造函数生成类实例

以上就是一次注入生成类实例的生成步骤。

@Scope

我们创建多一个Activity,这个Activity也注入了Poetry跟Gson对象:

1234567891011121314151617181920212223242526272829
public class OtherActivity extends AppCompatActivity {

    //添加@Inject注解,表示这个mPoetry是需要注入的    @Inject    Poetry mPoetry;

    @Inject    Gson mGson;

    private TextView mTextView;

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

        MainComponent.getInstance()                .inject(this);

        initView();    }

    private void initView() {        mTextView = (TextView) findViewById(R.id.tv_poetry);        String json = mGson.toJson(mPoetry);        String text = json + ",mPoetry:"+mPoetry;        mTextView.setText(text);    }}

我们顺便也把MainComponent改成抽象类的形式,并添加返回MainComponent单例的方法,对应添加MainActivity跳转到OtherActivity的方法.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
@Component(modules = {MainModule.class,PoetryModule.class})public abstract class MainComponent {

    /**     * 需要用到这个连接器的对象,就是这个对象里面有需要注入的属性     * (被标记为@Inject的属性)     * 这里inject表示注入的意思,这个方法名可以随意更改,但建议就     * 用inject即可。     */    abstract void inject(MainActivity activity);

    abstract void inject(OtherActivity activity);

    private static MainComponent sComponent;    public static MainComponent getInstance(){        if (sComponent == null){            sComponent = DaggerMainComponent.builder().build();        }        return sComponent;    }}

public class MainActivity extends AppCompatActivity {

    //添加@Inject注解,表示这个mPoetry是需要注入的    @Inject    Poetry mPoetry;

    @Inject    Gson mGson;

    private TextView mTextView;

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

        // 使用Dagger2生成的类 生成组件进行构造,并注入        MainComponent.getInstance()                .inject(this);

        initView();    }

    private void initView() {        mTextView = (TextView) findViewById(R.id.tv_poetry);        String json = mGson.toJson(mPoetry);        String text = json + ",mPoetry:"+mPoetry;        mTextView.setText(text);

        findViewById(R.id.open).setOnClickListener(view ->                startActivity(new Intent(this,OtherActivity.class)));    }}

运行结果如下:

可以看到,调用同一个MainComponent实例多次注入的时候每次都重新生成Poetry实例,有时候我们需要只希望生成一个共用实例的时候应该怎么办呢,这里我们就需要用到Dagger2的@Scope属性了,Scope是作用域的意思,我们先自定义一个@Scope注解:

1234
@Scope@Retention(RetentionPolicy.RUNTIME)public @interface PoetryScope {}

同时在Module与Component加上这个自定义Scope:

12345678910111213141516171819202122232425262728293031323334353637383940
@PoetryScope@Component(modules = {MainModule.class,PoetryModule.class})public abstract class MainComponent {    /**     * 需要用到这个连接器的对象,就是这个对象里面有需要注入的属性     * (被标记为@Inject的属性)     * 这里inject表示注入的意思,这个方法名可以随意更改,但建议就     * 用inject即可。     */    abstract void inject(MainActivity activity);

    abstract void inject(OtherActivity activity);

    private static MainComponent sComponent;    public static MainComponent getInstance(){        if (sComponent == null){            sComponent = DaggerMainComponent.builder().build();        }        return sComponent;    }}

@Modulepublic class PoetryModule {

    // 这个方法需要一个String参数,在Dagger2注入中,这些参数也是注入形式的,也就是    // 要有其他对方提供参数poems的生成,不然会造成编译出错    @PoetryScope    @Provides    public Poetry providePoetry(String poems){        return new Poetry(poems);    }

    // 这里提供了一个生成String的方法,在这个Module里生成Poetry实例时,会查找到这里    // 可以为上面提供String类型的参数    @Provides    public String providePoems(){        return "只有意志坚强的人,才能到达彼岸";    }}

重新运行:

这时你会发现这两个Poetry实例是同一个实例来的,通过实现自定义@Scope注解,标记当前生成对象的使用范围,标识一个类型的注射器只实例化一次,在同一个作用域内,只会生成一个实例,然后在此作用域内共用一个实例。这样看起来很像单例模式,我们可以查看@Singleton其实就是@Scope的一个默认实现而已。当然,你得是同一个Component对象来生成,这点我们应该可以理解的吧。
我们可以通过自定义Scope来组织Component的作用域,使得每个Component的作用域清晰明了,各施其职。

组织Component

我们在一个项目之中不可能只使用一个Component连接器来注入对象完成注入工作,一般除了一个全局的ApplicationComponent之外,还有一些作用域在Activity/Fragment的Component,Component之间存在依赖关系与从属关系。如果我们已经创建好了一个全局的ApplicationComponent,然后其它的Component刚好需要ApplicationComponent里面的一个全局属性,想要与ApplicationComponent共享同一个实例,这时就需要用到依赖关系了。

依赖方式

一个Component可以依赖一个或多个Component,并拿到被依赖Component暴露出来的实例,Component的dependencies属性就是确定依赖关系的实现。
这里的有点像数学里面的交集方式,被依赖的Component主动暴露对象给二者共享,如我们在ApplicationModule提供了一个全局的Gson对象,我们想要提供给其他Component时,要在ApplicationComponent显式的提供一个接口:

123456789101112131415161718192021
@Modulepublic class ApplicationModule {

    /**     * @Provides 注解表示这个方法是用来创建某个实例对象的,这里我们创建返回Gson对象     * 方法名随便,一般用provideXXX结构     * @return 返回注入对象     */    @Singleton    @Provides    public Gson provideGson(){        return new Gson();    }}

@Singleton@Component(modules = ApplicationModule.class)public interface ApplicationComponent {

    Gson getGson();// 暴露Gson对象接口}

并在自定义的MainApplication中初始化它,更改MainComponent:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
public class MainApplication extends Application {

    private ApplicationComponent mApplicationComponent;    private static MainApplication sApplication;

    public static MainApplication getInstance() {        return sApplication;    }    @Override    public void onCreate() {        super.onCreate();        sApplication = this;

        mApplicationComponent = DaggerApplicationComponent.builder().build();    }

    public ApplicationComponent getApplicationComponent() {        return mApplicationComponent;    }}

//这里表示Component会从MainModule类中拿那些用@Provides注解的方法来生成需要注入的实例@PoetryScope@Component(dependencies = ApplicationComponent.class, modules = {MainModule.class,PoetryModule.class})public abstract class MainComponent {

    /**     * 需要用到这个连接器的对象,就是这个对象里面有需要注入的属性     * (被标记为@Inject的属性)     * 这里inject表示注入的意思,这个方法名可以随意更改,但建议就     * 用inject即可。     */    abstract void inject(MainActivity activity);

    abstract void inject(OtherActivity activity);

    private static MainComponent sComponent;    public static MainComponent getInstance(){        if (sComponent == null){            sComponent = DaggerMainComponent.builder()                    .applicationComponent(MainApplication.getInstance()                    .getApplicationComponent())                    .build();        }        return sComponent;    }}

这样就达到了MainComponent依赖ApplicationComponent。并且这里需要注意的是,MainComponent的作用域不能和ApplicationComponent的作用域一样,否则会报错,一般来讲,我们应该对每个Component都定义不同的作用域。

包含方式(从属方式)@SubComponent

如果我们需要父组件全部的提供对象,这时我们可以用包含方式而不是用依赖方式,相比于依赖方式,包含方式不需要父组件显式显露对象,就可以拿到父组件全部对象。且SubComponent只需要在父Component接口中声明就可以了。添加多一个AActivity,AComponent:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
@Scope@Retention(RetentionPolicy.RUNTIME)public @interface AScope {}

@Modulepublic class AModule {

    @AScope    @Provides    public Poetry getPoetry(){        return new Poetry("万物美好");    }}

@AScope@Subcomponent(modules = AModule.class)public interface AComponent {    void inject(AActivity activity);}

@Singleton@Component(modules = ApplicationModule.class)public interface ApplicationComponent {

    Gson getGson();// 暴露Gson对象接口

    //AComponent plus();    AComponent plus(AModule module);//添加声明}

public class MainApplication extends Application {

    private ApplicationComponent mApplicationComponent;    private AComponent mAComponent;    private static MainApplication sApplication;

    public static MainApplication getInstance() {        return sApplication;    }    @Override    public void onCreate() {        super.onCreate();        sApplication = this;

        mApplicationComponent = DaggerApplicationComponent.builder().build();    }

    public ApplicationComponent getApplicationComponent() {        return mApplicationComponent;    }

    public AComponent getAComponent() {        if (mAComponent == null){            mAComponent = mApplicationComponent.plus(new AModule());        }        return mAComponent;    }}

public class AActivity extends AppCompatActivity {    TextView mTextView;

    @Inject    Gson mGson;

    @Inject    Poetry mPoetry;

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

        MainApplication.getInstance()                .getAComponent()                .inject(this);

        mTextView = (TextView) findViewById(R.id.text);        String text = mPoetry.getPoems()+",mPoetry:"+mPoetry+(mGson == null ? "Gson没被注入" : "Gson已经被注入");        mTextView.setText(text);    }}

最后我们在OtherActivity中添加一个按钮跳转到AActivity,运行结果如下:

@Qualifier

假如在上面的AActivity里面我们想要注入两个不同的Poetry(指peoms不一样)实例,我们可以在AModule下添加多一个生成Poetry的方法:

123456789101112131415
@Modulepublic class AModule {

    @AScope    @Provides    public Poetry getPoetry(){        return new Poetry("万物美好");    }

    @AScope    @Provides    public Poetry getOtherPoetry(){        return new Poetry("我在中间");    }}

但是直接这样做Dagger2是无法区分调用哪个方法生成Poetry实例的,这个时候就需要自定义@Qualifier限定符来匹配注入方法了,添加一个自定义Qualifier并修AMoudule,AActivity:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
@Qualifier@Documented@Retention(RetentionPolicy.RUNTIME)public @interface PoetryQualifier {    String value() default "";}

@Modulepublic class AModule {

    @PoetryQualifier("A")    @AScope    @Provides    public Poetry getPoetry(){        return new Poetry("万物美好");    }

    @PoetryQualifier("B")    @AScope    @Provides    public Poetry getOtherPoetry(){        return new Poetry("我在中间");    }}

public class AActivity extends AppCompatActivity {    TextView mTextView;

    @Inject    Gson mGson;

    // 匹配Module中同样注解的方法    @PoetryQualifier("A")    @Inject    Poetry mPoetry;

    // 匹配Module中同样注解的方法    @PoetryQualifier("B")    @Inject    Poetry mPoetryB;

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

        MainApplication.getInstance()                .getAComponent()                .inject(this);

        mTextView = (TextView) findViewById(R.id.text);        String text = mPoetry.getPoems()+",mPoetryA:"+mPoetry+                mPoetryB.getPoems()+",mPoetryB:"+mPoetryB+                (mGson == null ? "Gson没被注入" : "Gson已经被注入");        mTextView.setText(text);    }}

重新编译运行:

而Dagger2已经默认帮我们实现了一个@Named:

12345678
@Qualifier@Documented@Retention(RUNTIME)public @interface Named {

    /** The name. */    String value() default "";}

跟我们自定义的PoetryQualifier其实是一样的。

后记

这篇是我参考了其他文章之后自己又重新总结一遍的,错误之处请帮忙指出,大家一起进步。除了以上常用到的注解之外,Dagger还提供了其他一些注解,如Set,Map类的注解,具体可以参考以下文章。

参考

Dagger2图文完全教程
Google官方MVP+Dagger2架构详解【从零开始搭建android框架系列(6)】
Android:dagger2让你爱不释手-基础依赖注入框架篇
Android:dagger2让你爱不释手-重点概念讲解、融合篇
Android:dagger2让你爱不释手-终结篇
Android:Dagger2学习之由浅入深

Demo地址

https://github.com/EvilBT/-Dagger2Demo

时间: 2024-08-03 17:03:52

Dagger2的使用的相关文章

Android实现文章+评论(MVP,RxJava,Dagger2,ButterKnife)

简介 这个项目主要有两个功能,一个加载网页/文章,另一个用来显示评论.并应用了MVP模式,Dagger2.RxJava.ButterKnife等开源框架.效果图如下: 结构 首先来看一下布局文件: <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.andr

使用dagger2进行依赖注入(基础篇)

0. 前言 Dagger2是首个使用生成代码实现完整依赖注入的框架,极大减少了使用者的编码负担,本文主要介绍如何使用dagger2进行依赖注入.如果你不还不了解依赖注入,请看这一篇. 1. 简单的依赖注入 首先我们构建一个简单Android应用.我们创建一个UserModel,然后将它显示到TextView中.这里的问题是,在创建UserModel的时候,我们使用了前文所说的hard init.一旦我们的UserModel的创建方式发生了改变(比如需要传入Context对象到构造函数),我们就需

【Dagger2】简介 配置 使用 MVP案例

简介 dagger2:https://github.com/google/dagger Maven Central  2.11版本jar包下载 dagger:https://github.com/square/dagger compile 'com.google.dagger:dagger:2.11'//2017-9-17最新版本为[2.11] annotationProcessor 'com.google.dagger:dagger-compiler:2.11'//dagger-compile

MVP+Dagger2+Rxjava+Retrofit+GreenDao 开发的小应用,包含新闻、图片、视频3个大模块,代码封装良好

练习MVP架构开发的App,算是对自己学过的知识做一个总结,做了有一段时间,界面还算挺多的,代码量还是有的,里面做了大量封装,整体代码整理得很干净,这个我已经尽力整理了.不管是文件(java.xml.资源文件)命名,还是布局设计尽量简单简洁,我对自己写代码的规范还是有信心的- -.代码不会写的很复杂,整个代码结构有很高的统一度,结构也比较简单清晰,方便理解.里面做了大量的封装,包括基类的构建和工具类的封装,再配合Dagger2的使用可以极大地减轻V层(Activity和Fragment)的代码,

Dagger2 使用初步

Dagger2 是一个Android依赖注入框架,由谷歌开发,最早的版本Dagger1 由Square公司开发.依赖注入框架主要用于模块间解耦,提高代码的健壮性和可维护性.Dagger 这个库的取名不仅仅来自它的本意“匕首”,同时也暗示了它的原理.Jake Wharton 在对 Dagger 的介绍中指出,Dagger 即 DAG-er,这里的 DAG 即数据结构中的 DAG——有向无环图(Directed Acyclic Graph).也就是说,Dagger 是一个基于有向无环图结构的依赖注入

【Android 进阶】Dagger2 系列:入门案例一

介绍 A fast dependency injector for Android and Java. 一个在 Android 和 Java 平台上使用的快速的依赖注入框架. 类似 java 开发中的 spring 框架,但使用难度比 spring 大一点点. 依赖注入框架主要用于模块间解耦,提高代码的健壮性和可维护性. 几个必须知道的概念: 什么是依赖: 如果在 Class A 中,有 Class B 的实例,则称 Class A 对 Class B 有一个依赖. 什么是依赖注入: 依赖注入就

Dagger2系列之使用方法

本系列只讲使用方法和使用中遇到的问题,如果还对dagger2还不了解的童鞋儿可以参考文章: http://www.jianshu.com/p/cd2c1c9f68d4 http://www.jianshu.com/p/94d47da32656 使用Dagger2的前提需要添加一些依赖: 1 在Project的 build.gradle文件添加以下内容 buildscript { repositories { jcenter() } dependencies { classpath 'com.an

可靠的功能测试 - Espresso和Dagger2

欢迎Follow我的GitHub, 关注我的CSDN. 可靠的功能测试, 意味着在任何时候, 获取的测试结果均相同, 这就需要模拟(Mock)数据. 测试框架可以使用Android推荐的Espresso. 模拟数据可以使用Dagger2, 一种依赖注入框架. Dagger2已经成为众多Android开发者的必备工具, 是一个快速的依赖注入框架,由Square开发,并针对Android做了特别优化, 已经被Google进行Fork开发. 不像其他的依赖注入器, Dagger2没有使用反射, 而是使

Dagger2 生成代码学习

接上一篇文章介绍了Dagger2的初步使用,相信刚接触的人会觉得很奇怪,怎么会有很多自己没有定义的代码出现,为什么Component的创建方式是那样的.为了搞清楚这些东西,我们需要查看一下Dagger2 生成的源代码.Dagger2 是一个DI框架,通过学习生成的代码也可以更好的理解Dagger2是如何做依赖注入的. 将上一篇文章中的工程在SublimeText中打开,结构如下图: 可以看到AppComponent 生成了 DaggerAppComponent,Dagger2的生成规则中,我们自

dagger2 重点笔记

官方架构例子,里面有个dagger2的结合的例子 https://github.com/googlesamples/android-architecture https://google.github.io/dagger Dagger2 通过注解来生成代码,定义不同的角色,主要的注解有:@Inject.@Module .@Component .@Provides .@Scope .@SubComponent 等. @Inject: 通常在需要依赖的地方使用这个注解.换句话说,你用它告诉Dagge