when the android meet dragger2

What is dragger2?

dragger是一个依赖注入框架,不同于传统的依赖注入框架的是,dragger的代码是使用代码生成器进行机器生成,区别于传统的DI框架依赖反射。所以,dragger2更适合于android开发。并且,dragger2是基于JSR330,通过@Inject注解标示依赖,这个注解可用于方法(method),域(field),构造函数(ctor)。


我们可以先看一下dragger2中的注解:

when the android meet dragger2_第1张图片

Module是用来注解依赖注入上下文(dependency injection context),该类定义了一系列用于注解的对象集合。而这个类中的方法如果返回依赖的对象,那么就应该使用@Provides进行注解。如果你希望返回的对象应该是个实体类(单例的),那么可以和@Singletion进行注解,那么只会返回同一个实例。


我们可以看到@Inject定义了需要DI的地方,而Modlue则是对象的提供者,那么到这里,我们必定需要一种机制作为桥梁,来连接二者,这就是@Component的作用,@Component是用于interface的注解,这个接口会被Dragger2用来生成代码,通常生成的代码都是有固定的范式的,比如,在这个接口名之前加一个Dragger作为前缀。这个生成的代码有一个create方法,它被用于配置对象(我们稍后会看到)


HOW TO USE:

对于Android Studio 需要在工程的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:1.5.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files

        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //添加apt命令
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

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

classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 
用于添加apt命令


然后切换到app的gradle中
 


代码如下:

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.chan.daggerdemo"
        minSdkVersion 14
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    apt 'com.google.dagger:dagger-compiler:2.0.2' //指定注解处理器
    compile 'com.google.dagger:dagger:2.0.2'  //dagger公用api
    provided 'org.glassfish:javax.annotation:10.0-b28'  //添加android缺失的部分javax注解
}

Example:

package com.vogella.android.dagger2simple;

public class NetworkApi {

    public boolean validateUser(String username, String password) {
        // imagine an actual network call here
        // for demo purpose return false in "real" life
        if (username == null || username.length() == 0) {
            return false;
        } else {
            return true;
        }
    }
} 

对于NetworkApi我们需要一个Moudle来生产它的对象:

package com.vogella.android.dagger2simple.modules;

import com.vogella.android.dagger2simple.NetworkApi;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;

@Module
public class NetworkApiModule {
    @Provides
    @Singleton
    public NetworkApi getNetwork(){
        return new NetworkApi();
    }
} 


getNetwork用于创建NetworkApi,并且还是单例的创建

package com.vogella.android.dagger2simple.components;

import android.app.Activity;

import com.vogella.android.dagger2simple.MainActivity;
import com.vogella.android.dagger2simple.NetworkApi;
import com.vogella.android.dagger2simple.modules.NetworkApiModule;

import javax.inject.Singleton;

import dagger.Component;

@Singleton
@Component(modules = {NetworkApiModule.class})

public interface DiComponent {
    // to update the fields in your activities
    void inject(MainActivity activity);
} 


点击build将会生成代码,这时候我们在application里面创建注入上下文,并且提供方法来访问:

package com.vogella.android.dagger2simple;

import android.app.Application;

import com.vogella.android.dagger2simple.components.DaggerDiComponent;
import com.vogella.android.dagger2simple.components.DiComponent;

public class MyApplication extends Application {
    DiComponent component;

    @Override
    public void onCreate() {
        super.onCreate();
        component = DaggerDiComponent.builder().build();
    }

    public DiComponent getComponent() {
        return component;
    }
} 

配置一下AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.vogella.android.dagger2simple" >

    <application
        android:name="MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest> 
我们可以看到DiComponent接口,它有一个inject方法,该方法的参数就是需要DI的类,你可以把它想象成容器,而Moudle是产生对象的,这些对象通过Component注入到容器当中,所以你可以看到:

package com.vogella.android.dagger2simple;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

import javax.inject.Inject;

public class MainActivity extends Activity {

    @Inject NetworkApi networkApi;

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

        ((MyApplication) getApplication()).getComponent().inject(this);

        boolean injected =  networkApi == null ? false : true;
        TextView userAvailable = (TextView) findViewById(R.id.target);
        userAvailable.setText("Dependency injection worked: " + String.valueOf(injected));
    }
} 


NetworkApi 便成功的注入到了MainActivity中,值得注意的是,需要配注入的域不能是私有级别的!

结果:

when the android meet dragger2_第2张图片

你可能感兴趣的:(when the android meet dragger2)