前言
关于@Provides
与@Binds
的用法,经常叫不准,特地记录找到区别和联系
@Provides
无参
@Singleton
@Provides
static List<FragmentManager.FragmentLifecycleCallbacks> provideFragmentLifecycles() {
return new ArrayList<>();
}
含参
@Singleton
@Provides
static Cache<String, Object> provideExtras(Cache.Factory cacheFactory) {
//noinspection unchecked
return cacheFactory.build(CacheType.EXTRAS);
}
参数来源:
- 由
@Component
内通过modules
关联的其他@Module
提供
@Singleton
@Component(modules = {AppModule.class, ClientModule.class, GlobalConfigModule.class})
public interface AppComponent { ...
如上AppModule.class
内部Cache<String, Object> provideExtras
需要GlobalConfigModule.class
提供的数据(Cache.Factory
),因为是通过modules
相关联,所以可以直接调用到。
至于GlobalConfigModule.class
的数据(Cache.Factory
)也可以是由GlobalConfigModule.class
自己通过 @Provides
提供,也可以是通过@Component.Builder
注入。
- 由
@Module
内部的@Provides
方法提供 - 由
@Component
内通过dependencies
关联的其他@Module
提供
假设说,我们的LoginModule.class
也需要Cache.Factory
这个数据,此时Cache.Factory
由AppComponent.class
提供
@ActivityScope
@Component(modules = LoginModule.class, dependencies = AppComponent.class)
public interface LoginComponent {
因为是用dependencies
相关联,所以如果要用到Cache.Factory
就需要AppComponent.class
内部将Cache.Factory
声明(将Cache.Factory
开放给其他Component使用)出来,如下:
@Singleton
@Component(modules = {AppModule.class, ClientModule.class, GlobalConfigModule.class})
public interface AppComponent {
//....略
/**
* 用于创建框架所需缓存对象的工厂
*
* @return {@link Cache.Factory}
*/
Cache.Factory cacheFactory();
@Binds
@Binds
的语法和@Provides
的差距真是太大了,所以根本不能当成一样的看。
先看一段代码:
@Binds
@Named("ActivityLifecycle")
abstract Application.ActivityLifecycleCallbacks bindActivityLifecycle(ActivityLifecycle activityLifecycle);
@Binds
@Named("ActivityLifecycleForRxLifecycle")
abstract Application.ActivityLifecycleCallbacks bindActivityLifecycleForRxLifecycle(ActivityLifecycleForRxLifecycle
activityLifecycleForRxLifecycle);
了解一下:
-
@Named
😒 用于区分两个实例,如果返回值只有一个Application.ActivityLifecycleCallbacks
那么肯定是不需要@Named
了 -
Application.ActivityLifecycleCallbacks
:它是返回值,同时也是两个参数的父类,ActivityLifecycle
和ActivityLifecycleForRxLifecycle
都继承于它。 -
使用
@Inject
@Named("ActivityLifecycle")
protected Application.ActivityLifecycleCallbacks mActivityLifecycle;
@Inject
@Named("ActivityLifecycleForRxLifecycle")
protected Application.ActivityLifecycleCallbacks mActivityLifecycleForRxLifecycle;
和@Provides
并无差别。
@Provides
是通过自己通过new
或者build
(大部分build
内部也是new
实现)等创建类,那么@Binds
是怎么创建我们需要的对象呢?
通过参数ActivityLifecycle
和ActivityLifecycleForRxLifecycle
点入,我们发现内部其实就是完整的功能实现
发现他的构造函数:
@Singleton
public class ActivityLifecycle implements Application.ActivityLifecycleCallbacks {
//...略
@Inject
public ActivityLifecycle() {
}
这里就有必要了解一下 JSR330
: JSR330
是Jcp
给出的官方标准反向依赖注入规范。Java大部分反向依赖注入的工具或者框架目前基本上都满足 JSR330
规范、例如 spring
、guice
以及Dagger
。
JSR
中 @Inject
可以当做@AutoWired
来使用。其是用来定义自动注入的,而且与@AutoWired
一样,@Inject
可以标注在field
、method
或constructor
上。
即: @Inject 可以用于变量、方法、构造方法上! |
@Inject
会帮助当前类,通过调用注解标注的构造方法来创建实例。
绿色框的位置就是 @Inject
帮忙实现的部分。自己看吧!
总结
@Provides
与@Binds
都是提供依赖(可以理解成类的实例,接口实例)@Provides
与@Binds
对于创建有所区别。@Provides
是由开发者直接通过new
的方式参与其中;@Binds
是由开发者用@Inject
注解标注目标类的构造方法,由dagger
帮忙new
。- 无论是
@Provides
还是@Binds
,最后在使用的时候都是通过@Inject
引用,引用到的都是目标实例,创建好的那种。
参考地址
https://yq.aliyun.com/articles/626235?utm_content=m_1000013558
有问题随时欢迎沟通,相互学习。