当前位置: 移动技术网 > 移动技术>移动开发>Android > Dagger2 基础入门与使用

Dagger2 基础入门与使用

2020年08月14日  | 移动技术网移动技术  | 我要评论

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;
@Module
public 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<User> providerUserProvider;

  private MembersInjector<MainActivity> 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必须是单例的


@Module
public 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)
@Documented
public @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<T> implements Provider<T>, Lazy<T> {
  private static final Object UNINITIALIZED = new Object();

  private volatile Provider<T> provider;
  private volatile Object instance = UNINITIALIZED;

  private DoubleCheck(Provider<T> 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 <T> Provider<T> provider(Provider<T> delegate) {
    checkNotNull(delegate);
    if (delegate instanceof DoubleCheck) {
  
      return delegate;
    }
    return new DoubleCheck<T>(delegate);
  }

  /** Returns a {@link Lazy} that caches the value from the given provider. */
  public static <T> Lazy<T> lazy(Provider<T> provider) {
    if (provider instanceof Lazy) {
      @SuppressWarnings("unchecked")
      final Lazy<T> lazy = (Lazy<T>) provider;
    
      return lazy;
    }
    return new DoubleCheck<T>(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

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

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

  • 通过includes 引入到UserMoudle中
@Module(includes = {DataInfoModule.class}) //includes 引入moudle
public 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})//加载多个Moudle
public 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 引入moudle
public 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)
@Documented
public @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 注入方式的
@Inject
User user
DaggerMianComponent.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<User> providerUserProvider;

  private Provider<DataInfo> providerUserProvider2;

  private Provider<User> providerUserYProvider;

  private Provider<User> providerUserNProvider;

  private MembersInjector<MainActivity> 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;
    }
  }
}

本文地址:https://blog.csdn.net/Mr_kings/article/details/107959875

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网