Dagger2 依赖注入(Dependency injection ),通过注解的形式引入实体类,然后再接口Component作为桥梁沟通Moudle构建工厂模式注入到Activity/Fragment中减少我们new 实体化繁琐操作和统一管理我们的实列化对象

Dagger2官网地址

Gradle 引入 Dagger2

主目录gradle.build

dependencies {  classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'   }

项目gradle.build

dependencies {  compile 'com.google.dagger:dagger:2.11'  annotationProcessor 'com.google.dagger:dagger-compiler:2.11'  }
Dagger2注入流程图过程

注意:Component查找优先级Moudle高于Inject

Dagger2 基本使用 @Inject @Moudle @Provides @Component

通过@Inject User 对象,注入一次即可,多个构造函数无须多次注入

package com.lhw.daggerdemo.bean;import javax.inject.Inject;public class User {    private DataInfo mDataInfo;    public String name;    public int age;    public String tag;        @Inject    public User() {    }    public User(DataInfo data, String tagName) {        tag = tagName;        mDataInfo = data;    }    public User(String tagName) {        tag = tagName;    }    public User(DataInfo dataInof) {        mDataInfo = dataInof;    }}
新建Moudle实体类添加注解@Moudle,添加User实例化方法,给方法添加@Providers注解,提供对外@Component查找
import dagger.Module;import dagger.Provides;@Modulepublic class UserModule {    @Provides     User providerUser(){        return new User();    } }
新建接口MianComponent 添加@Component注解,添加 UserModule 到moudles中,然后新增一个inject 方法注入到Activity/Fragment中

注意:这里可以添加多个moudle,也可以通过dependencies依赖其他Component

@Component(modules ={UserModule.class})public interface MianComponent {    void inject(MainActivity activity);}
然后我们点击Build,rebuild project构建项目工程,就会在我们的App build输出目录下面generated/ap_generated_sources/debug/out/packageName/下面出现我们的构建的工厂实体实体类
public final class DaggerMianComponent implements MianComponent {    ... private Provider providerUserProvider;  private MembersInjector mainActivityMembersInjector;  private DaggerMianComponent(Builder builder) {    assert builder != null;    initialize(builder);  }  public static Builder builder() {    return new Builder();  }  public static MianComponent create() {    return new Builder().build();  }    @Override  public void inject(MainActivity activity) {    mainActivityMembersInjector.injectMembers(activity);  }    ...}
最后一步我们把构建好的实体类,注入到Activity/Fragment中
import javax.inject.Inject;import com.lhw.daggerdemo.component.DaggerMianComponent;public class MainActivity extends AppCompatActivity {    private final static String TAG="Dagger";       @Inject    User userY;//使用Inject 注解获取实例化对象User       @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //依赖绑定       DaggerMianComponent.create().inject(this);        userY.name="塞班";        userY.age=18;                      Log.d(TAG,"userY="+userY+",tag="+userY.tag);    }}//D/Dagger: userY=User{ name='塞班', age=18}

注意如果 User 里没有添加@Inject注解,只要在Moudle中添加了@Provides提供的User 对象,在inject 注入的Activity/Fragment 一样可以调用

注解@Singleton单列的使用

注意:
如果moudle 所依赖的Component中有被单例的对象,那么Component必须是单例的

@Modulepublic class UserModule {    @Provides @Singleton    User providerUser(){        return new User();    }    @Singleton @Component(modules ={UserModule.class})public interface MianComponent {    void inject(MainActivity activity);}   
注解@Singleton与@Scope的区别

都是限定区域的单例形式,实现同生共死,只是@Singleton是全局型的,而@Scope是局部范围的,@Scope注解在@Provides方法时,对使用@Provides提供的依赖生效;@Scope注解在类时,对使用@Inject注解的构造方法提供的依赖生效。

@Scope作用是控制所提供依赖的生命周期,使其与容器的生命周期相同,从而实现局部单例或全局单例

Singleton.java@Scope@Documented@Retention(RUNTIME)public @interface Singleton {}Scope.java@Target(ANNOTATION_TYPE)@Retention(RUNTIME)@Documentedpublic @interface Scope {}MianComponent.java@ActivityScope //添加注解实现局部单例@Component(modules ={UserModule.class})public interface MianComponent {    User getuser();    void inject(MainActivity activity);    }    
注意 自定义的@Singleton、@ActivityScope注解根本就没有这些功能,它的作用仅仅是“标记”,没有生成任何文件,只是多了一个DoubleCheck来进行单例的生成!
DaggerMianComponent.java  private void initialize(final Builder builder) {    this.providerUserProvider =        DoubleCheck.provider(UserModule_ProviderUserFactory.create(builder.userModule));    this.providerUserProvider2 =        DoubleCheck.provider(DataInfoModule_ProviderUserFactory.create(builder.dataInfoModule));    }

DoubleCheck.java 生成对应的单例的对象

public final class DoubleCheck implements Provider, Lazy {  private static final Object UNINITIALIZED = new Object();  private volatile Provider provider;  private volatile Object instance = UNINITIALIZED;  private DoubleCheck(Provider provider) {    assert provider != null;    this.provider = provider;  }  @SuppressWarnings("unchecked") // cast only happens when result comes from the provider  @Override  public T get() {    Object result = instance;    if (result == UNINITIALIZED) {      synchronized (this) {        result = instance;        if (result == UNINITIALIZED) {          result = provider.get();                Object currentInstance = instance;          if (currentInstance != UNINITIALIZED && currentInstance != result) {            throw new IllegalStateException("Scoped provider was invoked recursively returning "                + "different results: " + currentInstance + " & " + result + ". This is likely "                + "due to a circular dependency.");          }          instance = result;              provider = null;        }      }    }    return (T) result;  }  /** Returns a {@link Provider} that caches the value from the given delegate provider. */  public static  Provider provider(Provider delegate) {    checkNotNull(delegate);    if (delegate instanceof DoubleCheck) {        return delegate;    }    return new DoubleCheck(delegate);  }  /** Returns a {@link Lazy} that caches the value from the given provider. */  public static  Lazy lazy(Provider provider) {    if (provider instanceof Lazy) {      @SuppressWarnings("unchecked")      final Lazy lazy = (Lazy) provider;          return lazy;    }    return new DoubleCheck(checkNotNull(provider));  }}
如果上面单例 @Singleton没有保持一致就会报错,错误由于下个节点

DataInfoModule 中使用了@Singleton而 UserModule和MianComponent没有使用时报出的错误

.MianComponent (unscoped) may not reference scoped bindings:@Component(modules ={UserModule.class})^      @Provides @Singleton com.lhw.daggerdemo.bean.DataInfo com.lhw.daggerdemo.module.DataInfoModule.providerUser()
注解@Module中的includes和@Component中的modules的使用

User.java 添加多个构造函数,添加 DataInfo对象

public class User {    private DataInfo mDataInfo;    public String name;    public int age;    public String tag;    @Inject    public User() {    }    public User(DataInfo data, String tagName) {        tag = tagName;        mDataInfo = data;    }    public User(String tagName) {        tag = tagName;    }    public User(DataInfo dataInof) {        mDataInfo = dataInof;    }

DataInfo.java

public class DataInfo {    @Inject    public DataInfo(){}    public String sex;    public int height;    @Override    public String toString() {        return "DataInfo{" +                "sex='" + sex + '\'' +                ", height=" + height +                '}';    }}

DataInfoModule.java

@Modulepublic class DataInfoModule {    @Provides    @Singleton    DataInfo providerUser(){        return new DataInfo();    }}

像上面那种情况我们可以有两种处理方式

  • 通过includes 引入到UserMoudle中
@Module(includes = {DataInfoModule.class}) //includes 引入moudlepublic class UserModule {    @Provides @Singleton    User providerUser(){        return new User();    }}@Singleton@Component(modules ={UserModule.class})public interface MianComponent {    void inject(MainActivity activity);}
  • 通过在MianComponent modules 引入 UserMoudle和 DataInfoModule
@Singleton@Component(modules ={UserModule.class, DataInfoModule.class})//加载多个Moudlepublic interface MianComponent {    void inject(MainActivity activity);}
注解@Named的使用

相当于用来区分多个实体类的别名两个构造函数

@Qualifier@Documented@Retention(RUNTIME)public @interface Named {    /** The name. */    String value() default "";}

给UserModule中User不同的构造添加Named

@Module(includes = {DataInfoModule.class}) //includes 引入moudlepublic class UserModule {    @Provides @Singleton    User providerUser(){        return new User();    }    @Named("userN")    @Provides  @Singleton    User providerUserN(){        return new User("userN");    }    @Named("userY")    @Provides @Singleton    User providerUserY(DataInfo data){        return new User(data,"userY");    }}

然后我们调用的时候也做标识区分

public class MainActivity extends AppCompatActivity {    private final static String TAG="Dagger";    @Inject    DataInfo dataInfo;    @Named("userY")    @Inject    User userY;//使用Inject 注解获取实例化对象User    @Named("userN")    @Inject    User userN;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //依赖绑定       DaggerMianComponent.create().inject(this);        userY.name="塞班";        userY.age=18;        userN.name="阿巴阿巴";        userN.age=10;        dataInfo.height=188;        dataInfo.sex="nice";        //对象调用        Log.d(TAG,"userY="+userY+",tag="+userY.tag+",DataInfo="+dataInfo);        Log.d(TAG,"userN="+userN+",tag="+userN.tag);    }}
注解@Qualifier的使用

和@Named的作用类似,都是用来区分类型,可以自定义类型,只能是基本数据类型、String、Enum、Class,包含其一维数组

//Qualifier.java@Target(ANNOTATION_TYPE)@Retention(RUNTIME)@Documentedpublic @interface Qualifier {}//自定义QualifierType.java@Qualifier@Retention(RetentionPolicy.RUNTIME)public @interface QualifierType {     String value() default "";     String value2() default "";}//UserModule.java中使用 @QualifierType ("vip")//默认的value一个属性@QualifierType (value2 = "nomal")//value2一个属性@QualifierType (value = "svip", value2 = "vip")//使用了两个属性

其他情况的应用

1.方法注入的应用:
此时@Sign不能注解在方法上,必须注解在对应的注入参数中。

 @Inject    public void injectUser(@QualifierType("vip") User user) {        mUser= user;    }

2.@Provides方法依赖关系的应用:

    @QualifierType("svip")    @Provides    public Bus provideUserVipType(@QualifierType("vip") String nameType) {        return new User(nameType);    }    @QualifierType("vip")    @Provides    public String provideNameType() {        return "高级唯爱皮";    }

注意 build构建对象的两种方式

这里就算我们不使用 @Inject 注入User对象,也能通过Moudle中@Provides提供的User对象,注入Component 的 mianComponent生成创建的工厂类 DaggerMianComponent 获取对应的对象

MianComponent.java 添加getUser获取Moudle中的User对象

@Singleton@Component(modules ={UserModule.class})public interface MianComponent {    User getuser();        void inject(MainActivity activity);    @Component.Builder    interface  Builder{        @BindsInstance        Builder appplication(Application application);        MianComponent build();    }}

MainActivity.java 两种实例化获取方式

//1.Inject 注入方式的@InjectUser userDaggerMianComponent.builder().build().inject(this); //2.不使用Inject 注入方式的MianComponent  mianComponent  = DaggerMianComponent.builder().build();User user=mianComponent.getUser();

Android Studio Make Build 生成 DaggerMianComponent

public final class DaggerMianComponent implements MianComponent {  private Provider providerUserProvider;  private Provider providerUserProvider2;  private Provider providerUserYProvider;  private Provider providerUserNProvider;  private MembersInjector mainActivityMembersInjector;  private DaggerMianComponent(Builder builder) {    assert builder != null;    initialize(builder);  }  public static MianComponent.Builder builder() {    return new Builder();  }  @SuppressWarnings("unchecked")  private void initialize(final Builder builder) {    this.providerUserProvider =        DoubleCheck.provider(UserModule_ProviderUserFactory.create(builder.userModule));    this.providerUserProvider2 =        DoubleCheck.provider(DataInfoModule_ProviderUserFactory.create(builder.dataInfoModule));    this.providerUserYProvider =        DoubleCheck.provider(            UserModule_ProviderUserYFactory.create(builder.userModule, providerUserProvider2));    this.providerUserNProvider =        DoubleCheck.provider(UserModule_ProviderUserNFactory.create(builder.userModule));    this.mainActivityMembersInjector =        MainActivity_MembersInjector.create(            providerUserProvider2, providerUserYProvider, providerUserNProvider);  }  @Override  public User getuser() {    return providerUserProvider.get();  }  @Override  public void inject(MainActivity activity) {    mainActivityMembersInjector.injectMembers(activity);  }  private static final class Builder implements MianComponent.Builder {    private UserModule userModule;    private DataInfoModule dataInfoModule;    private Application appplication;    @Override    public MianComponent build() {      if (userModule == null) {        this.userModule = new UserModule();      }      if (dataInfoModule == null) {        this.dataInfoModule = new DataInfoModule();      }      if (appplication == null) {        throw new IllegalStateException(Application.class.getCanonicalName() + " must be set");      }      return new DaggerMianComponent(this);    }    @Override    public Builder appplication(Application application) {      this.appplication = Preconditions.checkNotNull(application);      return this;    }  }}

更多相关文章

  1. getSystemService 的参数
  2. Android应用程序组件间通信(一)——Intent类简介
  3. ScrollView嵌套Linearlayout显示不全的解决办法
  4. Android使用SharedPreferences保存数组
  5. Android(安卓)内功心法(1.9)——java设计模式之装饰模式
  6. Android开发之Memory类的分析
  7. Android中如何获取IMEI号码
  8. Android(安卓)Handler Message Looper机制原理
  9. Android(安卓)设计模式之面向对象的六大原则

随机推荐

  1. Android(安卓)API Guides---Advanced Ren
  2. 采用原生控件+前端技术开发Android、iOS
  3. 学习文件读写的相关知识
  4. Android(安卓)AIDL IPC机制详解
  5. 实现Unity和Android进行交互
  6. [置顶] android fragment和activity的区
  7. android 显示GIF动画
  8. MingQQ Android版发布了,可以在Android手
  9. Android(安卓)2D画图类Path精炼详解
  10. Android(安卓)M App 永久隐藏导航栏的Sol