Dragger2 浅入浅出

一、简介

Square公司旗下两把匕首:左手一把ButterKnife,右手一把Dragger2

本文只是介绍如何让你去用Dragger2,具体介绍不多赘述。

作为理工男,让我看字还不如给我一打代码实在,边敲边熟悉这个框架,再去看那些文字描述,会事半功倍。

二、名词分析

依赖

class Phone{
    private Battery battery;
}

class Battery{

}

手机类(Phone)持有对电池(Battery)的引用,故称Phone类对Battery类有一个依赖。


注入
注入分三种:构造注入、接口注入、注解注入


构造注入

class Phone{
    private Battery battery;

    //通过构造方法中将battery注入
    public Phone(Battery battery){
        this.battery = battery;
    }
}

接口注入

public interface Injection<T>{
    void inject(T t);
}

class Phone implements Injection<Battery>{
    private Battery battery;

    //通过实例化的接口方法注入依赖
    void inject(Battery battery){
        this.battery = battery;
    }
}

注解注入


class Phone{
    //注解
    @Inject
    private Battery battery;
}

代码实现

各种注解的图解

以上是简介注解的图解


环境配置

Project Gradle

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.2'
        //添加的代码段
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

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

Module Gradle

apply plugin: 'com.android.application'
//注意添加这个plugin
apply plugin: 'android-apt'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"

    defaultConfig {
        applicationId "com.sinla.dragger2"
        minSdkVersion 19
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:25.3.0'

    // 添加的代码段
    compile 'com.google.dagger:dagger:2.0.2'
    apt 'com.google.dagger:dagger-compiler:2.0.2'
    provided 'org.glassfish:javax.annotation:10.0-b28'
}

接下来开始
sample1

class Phone{
    @Inject
    private Battery battery;

    //注:需要在Build Project之后才会出现DaggerAppComponent
    public Phone(){
        DaggerAppComponent.builder()
                .build()
                .inject(this);
    }
}

class Battery{
    @Inject
    public Battery(){};
}

@Component
interface AppComponent{
    void inject(Phone phone);
}

sample2
如果是构造函数有参数的怎么办?
这时候得引入@Module

class Phone{
    @Inject
    private Battery battery;

    //注:需要在Build Project之后才会出现DaggerAppComponent
    public Phone(){
        DaggerAppComponent.builder()
                //根据@Component(modules = AppModule.class)
                //build之后自动生成
                .appModule(new AppModule())
                .build()
                .inject(this);

        battery.say();
    }
}

class Battery{

    private static final String TAG = "Battery";
    private String name;
    @Inject
    public Battery(String name){
        this.name = name;
    };

    public void say(){
        Log.e(TAG, "say: " + name);
    }
}

//注意这边的改变
@Component(modules = AppModule.class)
interface AppComponent{
    void inject(Phone phone);
}

//从@provides方法提供的类型来搜索
@Module
public class AppModule {
    //方法名非必需以provider开头
    @Provides
    public String providerString(){
        return "Jack";
    }

    //以下和sample2无关
    //如果provider方法有参数的话
    //会自动从module里面寻找是否有返回该参数类型的provider
    //即该Provider会从 providerString中返回String作为参数
    @Provider
    public Object providerObject(String name){
        return new Object();
    }
}

sample3
基本常用的都差不多了,现在讨论如果Module里面有两个相同返回参数的该怎么办?
这时候得引入@Qualifier

/**
 * 如果Module 中有两个相同的 返回参数,即用来作为区分
 */
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface QualifierA {
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface QualifierB {
}

class Phone{
    @QualifierA
    @Inject
    private Battery battery1;

    @QualifierB
    @Inject
    private Battery battery2;

    public Phone(){
        DaggerAppComponent.builder()
                .appModule(new AppModule())
                .build()
                .inject(this);
        battery1.say();
        battery2.say();
    }

}

class Battery{

    private static final String TAG = "Battery";
    private String name;
    @Inject
    public Battery(String name){
        this.name = name;
    };

    public void say(){
        Log.e(TAG, "say: " + name);
    }
}

@Component(modules = AppModule.class)
interface AppComponent{
    void inject(Phone phone);
}

@Module
public class AppModule {

    @QualifierA 
    @Provides
    public String providerStringJack(){
        return "Jack";
    }

    @QualifierB
    @Provides
    public String providerStringWilliam(){
        return "William";
    }
}

输出:
say:jack
say:william


sample4
接下来可以继续讨论如果构造函数传入的参数对象,能否变成单例化?
这时候得引入@Scope

/**
 * 局部单例化,仅创建一次
 * 类似于 @Singleton
 */
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface AppScope {
}

class Phone{

    @Inject
    private Battery battery1, battery2;

    public Phone(){
        DaggerAppComponent.builder()
                .appModule(new AppModule())
                .build()
                .inject(this);
        battery1.say();
        battery2.say();
    }

}

class Battery{

    private static final String TAG = "Battery";
    private User user;
    @Inject
    public Battery(User user){
        this.user = user;
    };

    public void say(){
        Log.e(TAG, "say: " + user.hashCode());
    }


}

//用来判断HashCode
public class User{
    private static final String TAG = "User";
    public User(){
        Log.e(TAG, "new instance");
    }
}

//注意此处加上@AppScope
@AppScope
@Component(modules = AppModule.class)
interface AppComponent{
    void inject(Phone phone);
}

@Module
public class AppModule {

    //注意此处加上@AppScope
    @AppScope
    @Provides
    public User providerUser(){
        return new User();
    }

}

输出:
User:new instance
Battery:”say:”:@11111
Battery:”say:”:@11111

可见User只有实例一次

结束

第一次写博客,纯手敲,有什么疏漏欢迎指出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值