new出来)从而提供依赖,另一个作用就是标记在需要依赖的变量让Dagger2为其提供依赖。
- @Provide 用Provide来标注一个方法,该方法可以在需要提供依赖时被调用,从而把预先提供好的对象当做依赖给标注了@Injection的变量赋值。provide主要用于标注Module里的方法
- @Module 用Module标注的类是专门用来提供依赖的。有的人可能有些疑惑,看了上面的@Inject,需要在构造函数上标记才能提供依赖,那么如果我们需要提供 的类构造函数无法修改怎么办,比如一些jar包里的类,我们无法修改源码。这时候就需要使用Module了。Module可以给不能修改源码的类提供依 赖,当然,能用Inject标注的通过Module也可以提供依赖
- @Component Component一般用来标注接口,被标注了Component的接口在编译时会产生相应的类的实例来作为提供依赖方和需要依赖方之间的桥梁,把相关依赖注入到其中。
看了这些概念我们回到刚才的例子当中:
我们对User的构造函数进行了 @Inject的标注 意思就是告诉Dagger2 如果有谁要使用User这个类,我标注的这个构造函数,你可以直接用来实例化该类;
然后我们在Activity中对User也进行了@Inject的标注 意思是告诉Dagger2 这个类需要被注入,简单的说就是 这个类我要用,你帮我实例化;
细心的读者可能会发现 这样会不会太简单了,是的 是太简单了不太正常,哈哈,上面的例子中还有一个标注@Component 光靠@Inject的标注是不足以完成注入的 我们需要用@Component来完成注入;
上例中被@Component标记的ActivityComponent接口就是一个注入器; void inject(MainActivity MainActivity);的意思是MainActivity中要用到这个注入器然后我们在MainActivity中对注入器进行初始化 DaggerActivityComponent.builder().build().inject(this); 然后Activity中所有被@Inject标记的类,都会通过ActivityComponent来进行初始化;
我们再把上例中的注入过程梳理一下:
1、首先定义一个类User 并在其构造函数用@Inject标注,表示告诉Dagger2这是我的构造函数,如果有地方要用到我,就用该构造函数对我实例化;
2、创建一个@Component标注的注入器接口,并在注入器中使用 void inject(MainActivity MainActivity);来表明哪里要用到注入器;
这里表示MainActivity中要用到该注入器
3、在MainActivity中对注入器进行初始化DaggerActivityComponent.builder().build().inject(this); 初始化后该注入器就可以正常使用了;
4、在MainActivity中对需要注入的类 User用@Inject进行标注,表示该类需要被注入,即实例化;
注意:在代码编写过程中 我们会发现DaggerActivityComponent会不存在,这是因为注入器是在编译的过程中才生成,所以我们在对注入器编写完成后
Make Project 一下就会生成DaggerActivityComponent
————————————————————————————————————————————————————————————————————————————————
现在我们已经明白了@InJect @Component的作用了,接下来我们来研究@Module和@Provide
通过上面的例子我们发现 @Inject是对类的构造函数进行标注来进行实例化的,但是有些类,比如第三方OkHttpClient,我们是无法对其源码进行修改的
即对其构造函数进行标注,这个时候我们就用到了@Module
@Module是什么意思呢 @Module是和@Component配合使用的 意思就是告诉注入器,如果你在实例化对象的时候,没有找到合适的构造函数,你就来我这里找,@Module通常标注一个类,该类里面可以实例化各种类,Component在注入对象的时候先去Module中找,如果找不到就会检查所有被@Inject标注的构造函数;所以我们可以把OkHttpClient放到Module中;
1 @Module
2 public class ActivityMoudle {
3
4 @Provides
5 @Singleton
6 OkHttpClient provideOkHttpClient() {
7 HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
8 loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
9
10 Interceptor apikey = chain -> chain.proceed(chain.request().newBuilder()
11 .addHeader("apikey", Constants.Api_Key).build());
12
13 OkHttpClient okHttpClient = new OkHttpClient.Builder()
14 .readTimeout(Constants.HTTP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
15 .connectTimeout(Constants.HTTP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
16 .addInterceptor(apikey)
17 .addInterceptor(loggingInterceptor)
18 .build();
19
20 return okHttpClient;
21 }
22
23 }
以上代码我们不需要知道是干嘛的,我们只知道该类中的方法返回一个okHttpClient的实例;
一个被@Module标注的类用来返回一个okHttpClient的实例;
我们再来看一下在Component中的代码:
1 @Singleton
2 @Component(modules = ActivityMoudle.class)
3 public interface ActivityComponent {
4
5 void inject(MainActivity MainActivity);
6 }
可以看到标注头多了@Component(modules = ActivityMoudle.class),表示告诉注入器如果你要注入的类没有找到构造函数,你就去ActivityMoudle.class中找
@Provide 用来标注一个方法,告诉注入器,我标注的方法你可以用来提供实例;
@Singleton 顾名思义,标注该实例化的对象为单例
然后我们在Activity直接标注