本文介绍了Dagger 2 中@BindsInstance和多绑定的使用。

本文首发:http://yuweiguocn.github.io/

《咏柳》
碧玉妆成一树高,万条垂下绿丝绦。
不知细叶谁裁出,二月春风似剪刀。
-唐,贺知章

Dagger 2 在 Android 上的使用(一)
Dagger 2 在 Android 上的使用(二)
Dagger 2 在 Android 上的使用(三)
Dagger 2 在 Android 上的使用(四)
Dagger 2 在 Android 上的使用(五)
Dagger 2 在 Android 上的使用(六)

注解@BindsInstance

有些情况下当组件构造时数据才可用,你可能想把它的实例绑定到组件上,我们可以使用@BindsInstance注解完成。

Component可以有一个使用@Component.Builder注解的静态抽象类或接口,如果有必须满足以下条件:

  • 必须有一个抽象无参方法返回Component,通常为build()方法
  • 所有抽象方法必须有一个参数,返回值为void、Builder或Builder的父类型

@BindsInstance注解在Component.Builder的方法上或Subcomponent.Builder的方法上,用于绑定对象实例到组件上,例如绑定Application对象:

@Component(modules = PeopleModule.class)public interface  PeopleComponent {    void inject(PeopleActivity activity);    @Component.Builder    interface Builder{        PeopleComponent build();        @BindsInstance        PeopleComponent.Builder application(Application application);    }}

在组件构造时传入对象实例:

public class PeopleActivity extends Activity implements PeopleContract.View{    @Inject    Application app;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_splash);        DaggerPeopleComponent.builder().application(getApplication()).build().inject(this);        Log.d("debug", app.toString());    }}

这种方法和在Module的构造方法中传入实例然后提供实例是相同的,但通常绑定实例更为高效,相对于使用Module提供实例应该优先使用绑定对象实例完成相应功能

多绑定

我们可以使用Dagger2提供的多绑定功能将多个Module中的多个对象绑定中一个集合中,支持Set和Map集合。先看一个绑定到Set集合的例子:

@Modulepublic abstract class PeopleModule {    @Binds    @IntoSet    abstract People bindStudent(Student student);    @Binds    @IntoSet    abstract People bindWorker(Worker worker);    }

这里我们用到了注解@IntoSet,表示将提供的实例绑定到Set集合中。注意对于其它Module提供的People实例也会绑定到Set集合中

public class PeopleActivity extends Activity {    @Inject    Set peopleSet;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        DaggerPeopleComponent.create().inject(this);        Log.d("debug", peopleSet.toString());    }}

打印输出:

2018-11-13 21:46:29.849 18967-18967/? D/debug: [io.github.yuweiguocn.test.Worker@38555b0, io.github.yuweiguocn.test.Student@1eb04f3]

生成的代码:

public final class DaggerPeopleComponent implements PeopleComponent {  ...  private Set getSetOfPeople() {    return SetBuilder.newSetBuilder(2).add(new Student()).add(new Worker()).build();  }  @Override  public void inject(PeopleActivity activity) {    injectPeopleActivity(activity);  }  private PeopleActivity injectPeopleActivity(PeopleActivity instance) {    PeopleActivity_MembersInjector.injectPeopleSet(instance, getSetOfPeople());    return instance;  }  ...}

对于想直接提供多个实例的Set集合,可以使用注解@ElementsIntoSet完成:

@Modulepublic abstract class PeopleModule {    ...    @Provides    @ElementsIntoSet    static Set providePeopleSet() {        return new HashSet(Arrays.asList(new Student(), new Student()));    }}

使用注解@ElementsIntoSet时也可以返回一个空集合:

@Provides@ElementsIntoSetstatic Set providePeopleSet() {    return Collections.emptySet();}

PeopleActivity的代码保持不变,打印输出:

2018-11-13 21:58:20.795 19608-19608/? D/debug: [io.github.yuweiguocn.test.Student@38555b0, io.github.yuweiguocn.test.Worker@4781bae, io.github.yuweiguocn.test.Student@1eb04f3, io.github.yuweiguocn.test.Student@6014c29]

生成的代码如下:

public final class DaggerPeopleComponent implements PeopleComponent {  ...  private Set getSetOfPeople() {    return SetBuilder.newSetBuilder(3)        .addAll(PeopleModule_ProvidePeopleSetFactory.proxyProvidePeopleSet())        .add(new Student())        .add(new Worker())        .build();  }  @Override  public void inject(PeopleActivity activity) {    injectPeopleActivity(activity);  }  private PeopleActivity injectPeopleActivity(PeopleActivity instance) {    PeopleActivity_MembersInjector.injectPeopleSet(instance, getSetOfPeople());    return instance;  }  ...}

除了直接使用依赖注入的方式,也可以在Component中也可以提供Set集合:

@Component(modules = PeopleModule.class)public interface PeopleComponent {    void inject(PeopleActivity activity);        Set peopleSet();}

对比生成的代码只是原来的方法名改为我们指定的方法名了:

public final class DaggerPeopleComponent implements PeopleComponent {  ...  @Override  public void inject(PeopleActivity activity) {    injectPeopleActivity(activity);  }  @Override  public Set peopleSet() {    return SetBuilder.newSetBuilder(3)        .addAll(PeopleModule_ProvidePeopleSetFactory.proxyProvidePeopleSet())        .add(new Student())        .add(new Worker())        .build();  }  private PeopleActivity injectPeopleActivity(PeopleActivity instance) {    PeopleActivity_MembersInjector.injectPeopleSet(instance, peopleSet());    return instance;  }  ...}

我们也可以使用多绑定功能将对象绑定到Map集合中,需要指定对应的key:

@Modulepublic abstract class PeopleModule {    @Binds    @IntoMap    @StringKey("stu")    abstract People bindStu(Student student);    @Binds    @IntoMap    @StringKey("work")    abstract People bindWork(Worker worker);}

这里用到了注解@IntoMap,表示将提供的对象绑定Map集合中,使用注解@StringKey指定了对应元素的key。

public class PeopleActivity extends Activity implements PeopleContract.View{    @Inject    Map peopleMap;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        DaggerPeopleComponent.create().inject(this);        Log.d("debug",peopleMap.toString());    }}

打印输出:

2018-11-15 17:33:04.786 11427-11427/? D/debug: {stu=io.github.yuweiguocn.dagger.test.Student@d732992, work=io.github.yuweiguocn.dagger.test.Worker@99f5f63}

除了可以使用StringKey指定Key的类型为String,还可以使用下图提供的注解,包括:ClassKey、IntKey、LongKey。如果有需要更复杂的Key的情况请参考官方文档。

Dagger 2 在 Android 上的使用(四)_第1张图片

提示:在编译时不知道Key的情况下可参考官方文档处理。

我们可以使用注解@Multibinds声明一个多绑定的Set或Map是绑定的。当至少有一个@IntoSet, @ElementsIntoSet, 或 @IntoMap绑定时,我们可以不用声明,但如果它们可能为空的情况下必须进行声明

@Modulepublic abstract class PeopleModule {    @Multibinds    abstract Set peopleSet();}

对于同样的返回类型声明多次并不会造成错误,因为Dagger2并没有实现或调用任何使用注解@Multibinds的方法。

总结

  • 注解@BindsInstance可以在组件构建时将传入的实例绑定到组件上,通过Module构造方法传入实例然后提供实例也可以完成相应功能,推荐使用绑定实例的方法
  • 多绑定可以将多Module中多个对象绑定到一个集合中,支持Set和Map集合
  • 使用多绑定时如果集合可能为空时需要使用@Multibinds注解进行声明

参考

  • https://google.github.io/dagger/
  • https://www.jianshu.com/p/24af4c102f62
  • http://www.cnblogs.com/tiantianbyconan/p/5092083.html

更多相关文章

  1. Android优秀实例源码
  2. [实例教程] 用python开发android应用
  3. Android中创建对话框(确定取消对话框、单选对话框、多选对话框)
  4. Android NDK入门实例 计算斐波那契数列一生成jni头文件
  5. android studio 3.6.0 绑定视图新特性的方法
  6. Android 应用程序只运行一个实例
  7. Android JNI入门实例
  8. Button简单实例1
  9. Android图片旋转实例

随机推荐

  1. android(17)_数据存储与访问_SQLite数据
  2. Android(安卓)分辨率与屏幕适配
  3. android 调用系统图片浏览器并返回图片路
  4. Android 四大组件之 Service
  5. android实现m3u8直播缓存/下载,M3U8Manger
  6. android中的启动模式
  7. Android捕获Home键
  8. Android常用颜色表
  9. Android(安卓)Study -- pmem driver代码
  10. android ndk开发中char和unsigned char问