参考:
Dagger2 使用(二)
Dagger 2 : Component.Builder注解有什么用?
在前面两篇
Dagger2 初探 (一)
Dagger2 初探 (二)
的基础上继续.
在前面学习了dagger2的基础之后就要正式开始在Android项目中使用dagger2了, 但是在https://github.com/google/dagger我还看到有一个叫做dagger.android
的扩展库, 是为了方便在Android中使dagger而生的, 但是当我在网上找资料去了解如何使用时, 却发现那么多博客讲的是云里雾里, 让人一脸懵逼, 更让人搞不懂的是它的原理.本以为学完前面的几个概念就可以直接上手dagger.android
了, 好吧, 我还是一步一步来吧.这篇依然是讲几个概念.后面再专门介绍dagger.android
@Component.Builder和@BindsInstance
先写一个简单的例子
AppComponent.java
1 |
|
AppModule.java
1 |
|
在MyApplication中实例化Component
1 | public class MyApplication extends Application { |
把程序跑起来, 打印结果:
1 | D/MyApplication: sharedPrefs = android.app.SharedPreferencesImpl@716e85e |
查看自动生成的类DaggerAppComponent.java
1 | public final class DaggerAppComponent implements AppComponent { |
特别注意里面这个内部类DaggerAppComponent.Builder
1 | public static final class Builder { |
可以看到这个内部类现在有一个成员变量appModule, 另外注意它这个appModule(AppModule appModule)这个方法.
好的, 注意完了.现在让我们使用@Component.Builder
和@BindsInstance
来改写上面的代码
我们看到之前AppModule的构造函数中需要传入一个Application参数, 而使用@BindsInstance和@Component.Builder就会方便一些了.
改写AppModule.java
1 |
|
可以看到providePreferences方法需要一个Application参数.
现在再改写AppComponent.java
1 |
|
再修改MyApplication中的代码:
1 | public class MyApplication extends Application { |
可以看到相比之前, 少了appModule(AppModule appModule)
方法, 多了application(Application application)
方法
查看修改后生成的DaggerAppComponent.java文件
1 | public final class DaggerAppComponent implements AppComponent { |
我们发现DaggerAppComponent.Builder有两个成员变量了, appMoudle 通过默认构造函数生成, 另一个成员变量 application是并通过 @BindsInstance 注解过的方法public Builder application(Application application)
来初始化的。
这里面具体的原理我就不深究了
总结:
- 如果使用
@Component.Builder
和@BindsInstance
来自定义 Builder 类,那么被@BindsInstance注解方法里面的参数在 Builder 类中都有对应的成员变量。
使用场景:
- 如果我们的 Moudle 某个被 @Provides 注解的 provide**(xxx obj) 函数使用了某种类型的对象作为参数 (比如 application),而这个参数如果不想通过 Moudle 构造函数传递进来,那么就可以使用 @Component.Builder 来自定义 Builder 类,并通过 @BindsInstance 注解的方法来提供这个参数 obj。
- 或者直接给 Component 直接添加一个对象依赖的提供函数。
@Subcomponent.Builder
关于@Subcomponent.Builder
, 几篇博客都说和@Component.Builder
类似,不过它是在subcomponents中使用, 但是都没有明确说明使用方法.
在开始讲@Subcomponent.Builder之前我们需要先回顾一下@Subcomponent的知识, 直接上例子吧.
FatherComponent.java
1 | (modules = FatherModule.class) |
FatherComponent需要提供一个方法返回SonComponent, 这是为了与SonComponent建立联系.
FatherModule用于提供Father对象, 代码如下:
1 |
|
SonComponent.java, 在这里就用到了@Subcomponent
了
1 | (modules = SonModule.class) |
SonModule.java用于提供Son对象
1 |
|
现在目标是要在SubcomponentActivity中同时注入Father对象和Son对象, 需要这样使用:
1 | public class SubcomponentActivity extends AppCompatActivity { |
首先获取FatherComponent, 然后通过FatherComponent获取SonComponent, 然后注入activity中
打印结果:
1 | D/SubcomponentActivity: father = me.mundane.componentbuilder.bean.Father@e847cc9 |
可以看到注入成功.
现在开始使用@Subcomponent.Builder, 改写上面的代码.
首先是, Son的构造函数变了, 需要一个String类型的参数
1 | public class Son { |
然后SonModule.java的代码也变了
1 |
|
接着是SonComponent.java变了
1 | (modules = SonModule.class) |
可以看到, SonModule中需要的String参数是从这里传入的.
接着改变FatherComponent
1 | (modules = FatherModule.class) |
之前这里返回的类型是子Component, 但是现在, 子Component在构建的时候我们是需要设置参数的, 如果直接返回的就是子Component, 我们还怎么给它设置参数呢?所以我猜测这里返回的应该是一个子Component的builder对象, 然后继续使用这个builder对象传入参数然后最后构建成子Component.
最后是Activity中的代码:
1 | public class SubcomponentActivity extends AppCompatActivity { |
打印结果:
1 | D/SubcomponentActivity: father = me.mundane.componentbuilder.bean.Father@e847cc9 |
以上均只是我的个人猜测用法.
唯一找到一篇关于@Subcomponent.Builder
的用法的博客是这篇Android_Dagger2 篇——从小白最易上手的角度 + 最新 dagger.android
可以自己写个demo试一下