Android Dagger2 基础 二

在Dagger2 基础一种我们讲解了@Inject等四个基本的关键字。
在该章节种我们将讲解@Named关键字和Lazy类。

@Named

在依赖迷失时给出方向。
依赖迷失:在上面的代码的基础上,如果我在TeacherModule.java中定义两个返回值是String的方法。这种情况下,在依赖注入的时候Dagger2 这个时候就不知道注入哪一个了。这种情况就角依赖迷失。

示例:

// **************TeacherModule.java**************
@Module
public class TeacherModule {
    @Provides
    public String getTeacherName() {
        return "HanMeimei";
    }

    @Provides
    public String getTeacherAge() {
        return "18";
    }
}

// **************MainActivity.java**************
public class MainActivity extends AppCompatActivity {
    @Inject String mName;
    @Inject String mAge;
复制代码

编译报错
E:\Sources\TestDagger2\app\src\main\java\com\example\testdagger2\ActivityComponent.java:7: ����: java.lang.String is bound multiple times:
void inject(MainActivity MainActivity);
^ @Provides String com.example.testdagger2.TeacherModule.getTeacherName()
@Provides String com.example.testdagger2.TeacherModule.getTeacherAge()

所以可以在TeacherModule的方法上添加上@Named关键字,同时在MainActivity的地方同样添加上关键字:

// **************TeacherModule.java**************
@Module
public class TeacherModule {
    @Named("name")
    @Provides
    public String getTeacherName() {
        return "HanMeimei";
    }

    @Named("age")
    @Provides
    public String getTeacherAge() {
        return "18";
    }
}

// **************MainActivity.java**************
public class MainActivity extends AppCompatActivity {
    @Inject @Named("name") String mName;
    @Inject @Named("age") String mAge;
复制代码

这个时候再次查看编译出来的文件,就会发现已经生成了关于name和age的单独的TeachModule文件,同时在MainActvity和ActivityComponent生成的文件中也增加了新的变量,确认name和age。
编译文件如下:

//************MainActivity_MembersInjector.java************
@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
  private final Provider<ClassRoom> mClassRoomProvider;

  private final Provider<Teacher> mTeacherProvider;

  private final Provider<String> mNameProvider;

  private final Provider<String> mAgeProvider;

  public MainActivity_MembersInjector(
      Provider<ClassRoom> mClassRoomProvider,
      Provider<Teacher> mTeacherProvider,
      Provider<String> mNameProvider,
      Provider<String> mAgeProvider) {
    assert mClassRoomProvider != null;
    this.mClassRoomProvider = mClassRoomProvider;
    assert mTeacherProvider != null;
    this.mTeacherProvider = mTeacherProvider;
    assert mNameProvider != null;
    this.mNameProvider = mNameProvider;
    assert mAgeProvider != null;
    this.mAgeProvider = mAgeProvider;
  }

  public static MembersInjector<MainActivity> create(
      Provider<ClassRoom> mClassRoomProvider,
      Provider<Teacher> mTeacherProvider,
      Provider<String> mNameProvider,
      Provider<String> mAgeProvider) {
    return new MainActivity_MembersInjector(
        mClassRoomProvider, mTeacherProvider, mNameProvider, mAgeProvider);
  }

  @Override
  public void injectMembers(MainActivity instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.mClassRoom = mClassRoomProvider.get();
    instance.mTeacher = mTeacherProvider.get();
    instance.mName = mNameProvider.get();
    instance.mAge = mAgeProvider.get();
  }

  public static void injectMClassRoom(
      MainActivity instance, Provider<ClassRoom> mClassRoomProvider) {
    instance.mClassRoom = mClassRoomProvider.get();
  }

  public static void injectMTeacher(MainActivity instance, Provider<Teacher> mTeacherProvider) {
    instance.mTeacher = mTeacherProvider.get();
  }

  public static void injectMName(MainActivity instance, Provider<String> mNameProvider) {
    instance.mName = mNameProvider.get();
  }

  public static void injectMAge(MainActivity instance, Provider<String> mAgeProvider) {
    instance.mAge = mAgeProvider.get();
  }
}

//**************DaggerActivityComponent.java**************
@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class DaggerActivityComponent implements ActivityComponent {
  private Provider<Teacher> getTeacherProvider;

  private Provider<String> getTeacherNameProvider;

  private Provider<String> getTeacherAgeProvider;

  private MembersInjector<MainActivity> mainActivityMembersInjector;

  private DaggerActivityComponent(Builder builder) {
    assert builder != null;
    initialize(builder);
  }

  public static Builder builder() {
    return new Builder();
  }

  public static ActivityComponent create() {
    return builder().build();
  }

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.getTeacherProvider = TeacherModule_GetTeacherFactory.create(builder.teacherModule);

    this.getTeacherNameProvider = TeacherModule_GetTeacherNameFactory.create(builder.teacherModule);

    this.getTeacherAgeProvider = TeacherModule_GetTeacherAgeFactory.create(builder.teacherModule);

    this.mainActivityMembersInjector =
        MainActivity_MembersInjector.create(
            ClassRoom_Factory.create(),
            getTeacherProvider,
            getTeacherNameProvider,
            getTeacherAgeProvider);
  }

  @Override
  public void inject(MainActivity MainActivity) {
    mainActivityMembersInjector.injectMembers(MainActivity);
  }

  public static final class Builder {
    private TeacherModule teacherModule;

    private Builder() {}

    public ActivityComponent build() {
      if (teacherModule == null) {
        this.teacherModule = new TeacherModule();
      }
      return new DaggerActivityComponent(this);
    }

    public Builder teacherModule(TeacherModule teacherModule) {
      this.teacherModule = Preconditions.checkNotNull(teacherModule);
      return this;
    }
  }
}

//************TeacherModule_GetTeacherAgeFactory.java************
    ......
   
//************TeacherModule_GetTeacherNameFactory.java************
    ......
​```

复制代码

所以这个时候,我们直接调用mName和mAge对象的时候,程序可以正确的知道你想调用的是哪个对象。

@Qualifier

该关键字的作用其实跟@Named是一样的,其实应该说@Named就是一种已经封装好的@Qualifier。毕竟@Named的代码如下:

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

那么我们为什么还需要@Qualifier呢?通过@Qualifier我们可以自定义注解,非常简单的例子,比如我有两个老师,我可以把Name归为一类,把Age再归为另一类,这样代码看起来非常的清晰。

示例:

//首先,先定义一个自定义的注解Age
// ******************Age.java***************
package com.example.testdagger2;
​
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
​
import javax.inject.Qualifier;
​
import static java.lang.annotation.RetentionPolicy.RUNTIME;
​
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Age {
    /** The age. */
    String value() default "";
}
​
//然后修正我们的TeacherModule
@Module
public class TeacherModule {
​
    @Named("name1")
    @Provides
    public String getTeacherName() {
        return "HanMeimei";
    }
​
    @Age("age1")
    @Provides
    public String getTeacherAge() {
        return "18";
    }
​
    @Named("name2")
    @Provides
    public String getOtherTeacherName() {
        return "Lilei";
    }
​
    @Age("age2")
    @Provides
    public String getOtherTeacherAge() {
        return "20";
    }
}
​
//再修正我们的调用类MainActivity
    @Inject @Named("name1") String mName;
    @Inject @Age("age1") String mAge;
    @Inject @Named("name2") String mName2;
    @Inject @Age("age2") String mAge2;

这样我们就可以跟@Named一样解决依赖注入迷失的问题的。而且对变量也进行了归类,代码可读性大大提升。

Lazy

Lazy 等同于注入T,只是只有在你get它的时候,才会真正的生成T。也就是说当你第一次去get时,它才会去初始化这个实例。并且多次调用get方法,返回的是同一个对象T。通过Lazy的这种方式,我们就可以在真正需要加载View或者调用数据等等情况下才去获取对象,从而缩短应用初始化的时间,提升性能。

代码示例:

public class MainActivity extends AppCompatActivity {
    private TextView mTextView;
    @Inject Teacher mTeacher;
    @Inject Lazy<Teacher> mTeacher2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerActivityComponent.create().inject(this);
        mTextView = (TextView) findViewById(R.id.text);
        mTextView.setText(mTeacher.getTeacher1() + "\n" +mTeacher2.get().getTeacher2() + "\n" + mTeacher2.get() + "\n" + mTeacher2.get());
    }
}
复制代码

通过上面的代码,mTeacher可以直接获取到Teacher类的函数;而mTeacher2的话,必须通过get()方法获取到Teacher的实例之后,才能获取到函数。这说明Lazy这种方式只有在get它的时候,才会真正的生成对象。并且根据代码执行的结果,多次调用get()方法,返回的是同一个对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值