依赖注入框架-dragger2

来源:互联网 发布:淘宝没有销量 编辑:程序博客网 时间:2024/06/18 11:17

本文转载自:https://github.com/EvilBT/-Dagger2Demo

Dagger2 是一款使用在JavaAndroid上的依赖注入的一个类库,用来解耦的。

简单使用@inject:

配置信息

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

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

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

apply plugin: 'com.neenbedankt.android-apt'apply plugin: 'me.tatarka.retrolambda'//将jdk版本设置成1.8版本android {    compileOptions {        sourceCompatibility JavaVersion.VERSION_1_8        targetCompatibility JavaVersion.VERSION_1_8    }}dependencies {compile 'com.google.dagger:dagger:2.6'apt 'com.google.dagger:dagger-compiler:2.6'    provided 'org.glassfish:javax.annotation:10.0-b28'}

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

创建一个javabean类,如下:

public class Poetry {    private String mPemo;    // 用Inject标记构造函数,表示用它来注入到目标对象中去    @Inject    public Poetry() {        mPemo = "你看那朵云,像不像你欠我的那200块钱";    }    public String getPemo() {        return mPemo;    }}

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

//用@Component表示这个接口是一个连接器,能用@Component注解的只能是interface或者抽象类@Componentpublic interface MainComponent {    /**     * 需要用到这个连接器的对象,就是这个对象里面有需要注入的属性(被标记为@Inject的属性)     * 这里inject表示注入的意思,这个方法名可以随意更改,但建议就用inject即可。     */    void inject(MainActivity activity);}

运行一遍,AS中会根据我们写的连接类MainComponent来生成一些类



MainActivity中注入javabean类

如果不等AS生成上述源文件,使用DaggerMainComponent注入javabean就会报错:

public class MainActivity extends AppCompatActivity {    //添加@Inject注解,表示这个mPoetry是需要注入的    @Inject    Poetry mPoetry;    @InjectView(R.id.tv_poetry)    TextView tvPoetry;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ButterKnife.inject(this);        // 使用Dagger2生成的类 生成组件进行构造,并注入,注入完成后mPoetry才不为空        DaggerMainComponent.builder()                .build()                .inject(this);        tvPoetry.setText(mPoetry.getPemo());    }}

运行结果如下:


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


@Module

依赖moudle对象

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

添加Gson依赖:

compile 'com.google.code.gson:gson:2.2.4'


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

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

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

MainActivity里注入Gson实例

public class MainActivity extends AppCompatActivity {    //添加@Inject注解,表示这个mPoetry是需要注入的    @Inject    Poetry mPoetry;    @Inject    Gson mGson;    @InjectView(R.id.tv_poetry)    TextView tvPoetry;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ButterKnife.inject(this);        // 使用Dagger2生成的类 生成组件进行构造,并注入,注入完成后mPoetry才不为空        DaggerMainComponent.builder()                .build()                .inject(this);//        tvPoetry.setText(mPoetry.getPemo());        String json = mGson.toJson(mPoetry);        tvPoetry.setText(json);    }}

运行结果:

Component可以依赖多个Module对象.

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

@Modulepublic class PoetryModule {    // 这个方法需要一个String参数,在Dagger2注入中,这些参数也是注入形式的,也就是    // 要有其他对方提供参数poems的生成,不然会造成编译出错    @Provides    public Poetry providePoetry(String poems){        return new Poetry(poems);//注意要同步在Poetry中生成有参构造    }    // 这里提供了一个生成String的方法,在这个Module里生成Poetry实例时,会查找到这里    // 可以为上面提供String类型的参数    @Provides    public String providePoems(){        return "只有意志坚强的人,才能到达彼岸";    }}

修改MainComponent依赖:

@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中存在创建方法,则看此创建方法有没有参数

·如果有参数,这些参数也是由Component提供的,返回步骤1逐一生成参数类实例,最后再生成最终类实例

·如果无参数,则直接由这个方法生成最终类实例

3.Module中没有创建方法,则从构造函数里面找那个用@Inject注解的构造函数

·如果该构造函数有参数,则也是返回到步骤1逐一生成参数类实例,最后调用该构造函数生成类实例

·如果该构造函数无参数,则直接调用该构造函数生成类实例

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


友情提示:其他注解方式详解和demo下载地址请参考本文转载出处:https://github.com/EvilBT/-Dagger2Demo



1 0
原创粉丝点击