第一部分
dagger2是一个依赖注入的框架,举个例子如果我们不适用dagger注入,我们调用一个对象必须使用构造方法,这样就会造成了类与类的组合,但dagger的使用解决了这一问题。
这是dagger的官网
我们看一下跟dagger相关的概念,
@Inject
通常在需要依赖的地方使用这个注解。换句话说,你用它告诉Dagger这个类或者字段需要依赖注入。这样,Dagger就会构造一个这个类的实例并满足他们的依赖。 官方点说就是带有此注解的属性或构造方法将参与到依赖注入中,Dagger2会实例化有此注解的类。
@Module
Modules类里面的方法专门用来提供依赖,他就像一个工厂一样去生产需要添加依赖的实例。所以我们定义一个类,用@Module来注解,这样Dagger在构造类的实例的时候,就知道从哪里去找到需要的依赖。modules的一个重要特性是它们设计为分区并组合在一起(例如,我们的app中可以有多个组成在一起的modules)。它里面定义一些用@Provides注解的以provide开头的方法,这些方法就是所提供的依赖,Dagger2会在该类中寻找实例化某个类所需要的依赖。
@Provides
上面引入了这个概念了。在modules中,我们定义的方法是用@Provides这个注解,以此来告诉Dagger我们想要构造对象并提供这些依赖。
@Component
Components从根本上来说他就是一个注入器,也可以说是用来将@Inject和@Module联系起来的桥梁,它的主要作用就是连接这两个部分。Components可以提供所有定义了的类型的实例(inject需要),比如:我们必须用@Component注解一个接口然后列出所有的 。功能是从@Module中获取依赖并将依赖注入给@Inject
dagger必不可少的三个元素:Module,Component,Container
这里有张图来说明它们之间的关系。
dagger2222222222.png
第二部分 Dagger2的基本使用(上)
下面我们看下具体怎么使用
首先要导入依赖
dependencies {
implementation 'com.google.dagger:dagger:2.16'
annotationProcessor 'com.google.dagger:dagger-compiler:2.16'}
这里有个ApiService的类,我们需要在MainActivity中使用它的实例,如果我们不用dagger,我们就只能new ApiService()
,但是我们现在使用dagger,就不需要new了。
先看下ApiService这个没用的类
package com.example.dagger2test;
import android.util.Log;
public class ApiService {
public void register() {
Log.i("zhang_xin","register成功");
}
}
等下我们要使用dagger获取它的实例。
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
ApiService mApiService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
在MainActivity里我们使用@inject注解,告诉dagger,我需要ApiService的实例。dagger就会从@Component注释的接口中寻找ApiService的实例,那好,我们下面创建这个接口。
package com.example.dagger2test;
import dagger.Component;
@Component(modules = {?.class})//关联到module
public interface UserComponet {
}
大家看下Component的源码
public @interface Component {
/**
* A list of classes annotated with {@link Module} whose bindings are used to generate the
* component implementation. Note that through the use of {@link Module#includes} the full set of
* modules used to implement the component may include more modules that just those listed here.
*/
Class<?>[] modules() default {};
/**
* A list of types that are to be used as <a href="#component-dependencies">component
* dependencies</a>.
*/
Class<?>[] dependencies() default {};
可以发现,Component需要module,我们需要在?处传入我们的module
下面我们创建module
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
public class UseModule {
@Provides//提供依赖
public ApiService provideApiService(){
return new ApiService();
}
}
在module里我们真正创建ApiService的实例,这个提供ApiService实例的方法,我们需要标注为@provides
我们现在重新捋一下我们的思路
在MainActivity(就是图中Container)中,我们需要ApiService的实例,我们在ApiService上加上@inject注解,这样dagger就知道我们需要ApiService的实例,dagger就会去@Component注解下的类去找该实例,commponent是一个桥梁,它关联了很多modules。我们看下@Component的代码
package com.example.dagger2test;
import dagger.Component;
@Component(modules = {UseModule.class})
public interface UserComponet {
}
注意,以上只是Module与Component进行了关联,我说过Component是一个桥梁,所我们还需要把Component与MainActivity进行关联,
package com.example.dagger2test;
import dagger.Component;
@Component(modules = {UseModule.class})//关联到module
public interface UserComponet {
void inject(MainActivity activity);//关联到Activity
}
从这行注释@Component(modules = {UseModule.class})
,dagger就知道要去UseModule里获取ApiService的实例。
我们在看下UseModele类,在这个类里获取ApiService的实例,注意,该类需要添加@module
注解。提供对象的方法添加@Prividers
,方法的返回值为ApiService且有@Provides注释,那么dagger就会从这个方法里获取ApiService对象
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
@Provides//提供依赖
public ApiService provideApiService(){
return new ApiService();
}
}
到这里我们在MainActivity(Container)里调用ApiService实例的代码就全部完成了。然后我们rebuild我们的工程
这个时候dagger会自动生成DaggerUserComponet类,该类有个create()
,会生成UserComponet的实例,然后通过该实例我们调用UserComponet的inject方法。完整代码如下
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
/**
* 依赖注入框架,解决繁琐的依赖关系
* 必不可少的三种元素:Module,Component,Container,module提供依赖的集合,里面有很多方法是提供依赖的
* ,component
*/
public class MainActivity extends AppCompatActivity {
@Inject//dagger会从commponent里去找ApiService的实例。使用依赖
ApiService mApiService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//生成UserComponet的实例,调用inject()
DaggerUserComponet.create().inject(this);
mApiService.register();
}
}
运行会输出
10-20 15:22:10.585 22065-22065/com.example.dagger2test I/zhang_xin: register成功
为了方便大家看,我把所有相关的类在贴一遍。
package com.example.dagger2test;
import android.util.Log;
public class ApiService {
public void register() {
Log.i("zhang_xin","register成功");
}
}
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject//dagger会从commponent里去找ApiService的实例。使用依赖
ApiService mApiService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.create().inject(this);
mApiService.register();
}
}
package com.example.dagger2test;
import dagger.Component;
@Component(modules = {UseModule.class})//关联到module
public interface UserComponet {
void inject(MainActivity activity);//关联到Activity
}
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
@Provides//提供依赖
public ApiService provideApiService(){
return new ApiService();
}
}
第三部分 Dagger2的基本使用(下)
我们再来看一下复杂的例子。
我们需要MainActivity类里获取UserManager实例,UserManager的构造方法需要传入另外两个类的实例。我们看下UserManager类
package com.example.dagger2test;
public class UserManager {
private ApiService apiService;
private UserStore userStore;
public UserManager(ApiService apiService, UserStore userStore) {
this.apiService = apiService;
this.userStore = userStore;
}
public void register(){
apiService.register();
userStore.register();
}
}
这是UserStore类
package com.example.dagger2test;
import android.util.Log;
public class UserStore {
public void register(){
Log.i("zhang_xin","UserStore注册成功");
}
}
我们有两种方法
第一种,修改UseModule
文件
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
@Provides
public ApiService getApiService() {
return new ApiService();
}
@Provides
public UserStore getUserStore() {
return new UserStore();
}
@Provides
public UserManager getUserManager(ApiService apiService, UserStore userStore) {
return new UserManager(apiService, userStore);
}
}
然后在MainActivity中调用用
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.create().inject(this);
userManager.register();
}
}
看下打印输出结果
10-20 17:03:03.092 27717-27717/com.example.dagger2test I/zhang_xin: ApiService register成功 UserStore注册成功
第二种方法,使用构造方法。
我们先把UseModule中方法注释掉
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
// @Provides
// public ApiService getApiService() {
// return new ApiService();
// }
//
// @Provides
// public UserStore getUserStore() {
// return new UserStore();
// }
@Provides
public UserManager getUserManager(ApiService apiService, UserStore userStore) {
return new UserManager(apiService, userStore);
}
}
然后修改ApiService和UseModule两个类,添加@Inject注释的方法。
package com.example.dagger2test;
import android.util.Log;
import javax.inject.Inject;
public class UserStore {
@Inject
public UserStore(){
}
public void register(){
Log.i("zhang_xin","UserStore注册成功");
}
}
package com.example.dagger2test;
import android.util.Log;
import javax.inject.Inject;
public class ApiService {
@Inject
public ApiService() {
}
public void register() {
Log.i("zhang_xin", "ApiService register成功");
}
}
运行MainActivity
10-20 17:14:14.795 28228-28228/com.example.dagger2test I/zhang_xin: ApiService register成功 UserStore注册成功
由以上两种方法我们可以得出结论。
如果Module中没有提供@Providers注释的方法,Dagger会去调用@Inject注释的方法。
第四部分
我们现在有这么个需求,那就是UseModule的构造方法需要传入参数。我们修改下UseModule类
package com.example.dagger2test;
import android.content.Context;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
private Context context;
public UseModule (Context context){
this.context=context;
}
@Provides
public ApiService getApiService() {
return new ApiService();
}
@Provides
public UserStore getUserStore() {
return new UserStore(this.context);
}
@Provides
public UserManager getUserManager(ApiService apiService, UserStore userStore) {
return new UserManager(apiService, userStore);
}
}
现在大家看下,我们怎么在MainActivity类里调用
DaggerUserComponet.create().inject(this);
肯定是行不通了
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().useModule(new UseModule(this)).build().inject(this);
userManager.register();
}
}
第五部分
假设我们现在有这么一个需求,ApiService里需要传入一个参数(实际开发中可能是OkHttpClient等,我们这里只简单的使用Dog),我们可以这么做
,先看下Dog类
package com.example.dagger2test;
public class Dog {
}
看下UserManager类
package com.example.dagger2test;
public class UserManager {
private ApiService apiService;
private UserStore userStore;
public UserManager(ApiService apiService, UserStore userStore) {
this.apiService = apiService;
this.userStore = userStore;
}
public void register(){
apiService.register();
userStore.register();
}
}
看下ApiService类
package com.example.dagger2test;
import android.util.Log;
public class ApiService {
private Dog dog;
//注意 dog是单例对象
public ApiService(Dog dog) {
this.dog = dog;
}
public void register() {
Log.i("zhang_xin", "ApiService register成功");
}
}
我们可以单独写一个针对Dog类的DogModule
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class DogModule {
@Singleton//增加单例注释
@Provides
public Dog getUser(){
return new Dog();
}
}
然后在UseModule中引用DogMoudle
package com.example.dagger2test;
import android.util.Log;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
//includes引入另外一个module
@Module(includes = {DogModule.class})
public class UseModule {
@Provides
public ApiService getApiService(Dog dog) {
Log.i("zhang_xin", "dog是否是单例:" + dog.toString());
return new ApiService(dog);
}
@Provides
public UserStore getUserStore() {
return new UserStore();
}
@Provides
public UserManager getUserManager(ApiService apiService, UserStore userStore) {
return new UserManager(apiService, userStore);
}
}
同时UserComponet也需要修改
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Component;
//增加单例注释
@Singleton
@Component(modules = {UseModule.class})//关联到module
public interface UserComponet {
void inject(MainActivity activity);//关联到Activity
}
下面我们在MainActivity中调用
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().useModule(new UseModule()).dogModule(new DogModule()).build().inject(this);
userManager.register();
}
}
最后我们看一下打印输出
10-20 20:23:15.805 31622-31622/com.example.dagger2test I/zhang_xin: dog是否是单例:com.example.dagger2test.Dog@b45757d 10-20 20:23:15.809 31622-31622/com.example.dagger2test I/zhang_xin: ApiService register成功 UserStore注册成功
多次打印都是这个值:com.example.dagger2test.Dog@b45757d;
说明Dog确实是单例模式
除此之外还有一种方法,我们首先把UseModule恢复原来的样子
package com.example.dagger2test;
import android.util.Log;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
//这里删除includes
@Module
public class UseModule {
@Provides
public ApiService getApiService(Dog dog) {
Log.i("zhang_xin", "dog是否是单例:" + dog.toString());
return new ApiService(dog);
}
@Provides
public UserStore getUserStore() {
return new UserStore();
}
@Provides
public UserManager getUserManager(ApiService apiService, UserStore userStore) {
return new UserManager(apiService, userStore);
}
}
然后修改我们的UserComponet类
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
//增加DogModule.class
@Component(modules = {UseModule.class,DogModule.class})//关联到module
public interface UserComponet {
void inject(MainActivity activity);//关联到Activity
}
其余的代码不变,效果一样
第六部分 创建和区分不同实例(上)
我们现在有新的需求了,我们在MainActivity里需要两个ApiService对象,该怎么操作呢?其实也很简单,只需要在UseModule中提供两个@Provides注释的方法,同时在MainActivity和UseModule中添加@Named注释,注意MainActivity中的@Named和UseModule中的@Named字段要一一对应。看下代码更一目了然
ApiService类
package com.example.dagger2test;
import android.util.Log;
public class ApiService {
public void register() {
Log.i("zhang_xin", "ApiService register成功");
Log.i("zhang_xin",this.toString());
}
}
MainActivity需要两个ApiService类,每个对象前添加@Named注释
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import javax.inject.Inject;
import javax.inject.Named;
public class MainActivity extends AppCompatActivity {
@Named("1")
@Inject
ApiService apiService1;
@Inject
@Named("2")
ApiService apiService2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().useModule(new UseModule()).build().inject(this);
apiService1.register();
apiService2.register();
}
}
UseNodule类,添加@Named注释与MainActivity一一对应
package com.example.dagger2test;
import javax.inject.Named;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
@Provides
@Named("1")
public ApiService getApiService1(Dog dog) {
return new ApiService();
}
@Provides
@Named("2")
public ApiService getApiService2(Dog dog) {
return new ApiService();
}
}
看下打印输出
10-22 19:44:09.799 31505-31505/com.example.dagger2test I/zhang_xin: ApiService register成功 com.example.dagger2test.ApiService@b45757d 10-22 19:44:09.800 31505-31505/com.example.dagger2test I/zhang_xin: ApiService register成功 com.example.dagger2test.ApiService@20d4c72
可以看出两个ApiService的内存地址不一样,是两个不同的对象。
注意,如果我们不添加@Named注释,dagger会根据返回值类型进行匹配。
第七部分 dagger创建和区分不同实例(下)
上接第六部分,第六部分的功能我们还可以这样实现,自定义@Interface
我们首先自定义两个@Interface文件,一个叫@First,一个叫@Second
package com.example.dagger2test;
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 First {
}
package com.example.dagger2test;
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 Second {
}
在UseModule和MainActivity中,我们需要把@Named注释分别改为@First和@Second,我们看下代码
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import javax.inject.Inject;
import javax.inject.Named;
public class MainActivity extends AppCompatActivity {
@First
@Inject
ApiService apiService1;
@Second
@Inject
ApiService apiService2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().useModule(new UseModule()).build().inject(this);
apiService1.register();
apiService2.register();
}
}
package com.example.dagger2test;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
@Provides
@First
public ApiService getApiService1() {
return new ApiService();
}
@Provides
@Second
public ApiService getApiService2() {
return new ApiService();
}
}
看下运行效果
10-22 19:59:50.668 32434-32434/com.example.dagger2test I/zhang_xin: ApiService register成功 com.example.dagger2test.ApiService@b45757d ApiService register成功 10-22 19:59:50.669 32434-32434/com.example.dagger2test I/zhang_xin: com.example.dagger2test.ApiService@20d4c72
第八部分:Singleton 单例讲解(上)
我们需要ApiService是单例模式
首先我们看下ApiService类
package com.example.dagger2test;
import android.util.Log;
public class ApiService {
public void register() {
Log.i("zhang_xin", "ApiService register成功");
Log.i("zhang_xin",this.toString());
}
}
这个时候我们需要在Module类的方法中添加@Singleton注释,代码如下
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class UseModule {
@Singleton
@Provides
public ApiService getApiService() {
return new ApiService();
}
}
注意我们现在需要修改UserComponent类,他的类也需要添加@Singleton注释
package com.example.dagger2test;
import javax.inject.Singleton;
import dagger.Component;
@Singleton//因为UseModule添加了该注释,所以这里也需要添加注释
@Component(modules = {UseModule.class,DogModule.class})//关联到module
public interface UserComponet {
void inject(MainActivity activity);//关联到Activity
}
然后我们看下MainActivity
package com.example.dagger2test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import javax.inject.Inject;
import javax.inject.Named;
public class MainActivity extends AppCompatActivity {
@Inject
ApiService apiService1;
@Inject
ApiService apiService2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().useModule(new UseModule()).build().inject(this);
apiService1.register();
apiService2.register();
}
}
我们多次运行都会打印这个结果
10-22 20:33:15.896 3145-3145/com.example.dagger2test I/zhang_xin: ApiService register成功 com.example.dagger2test.ApiService@b45757d ApiService register成功 com.example.dagger2test.ApiService@b45757d
apiService1和apiService2内存地址一样,说明它们是同一个对象。
第八部分:Singleton 单例讲解(下)
我们第七部分实现了单例模式,但是这种方法实现的单例模式是有问题的,如果我们现在在创建一个MainActivity2和与之相关的@Component注释的类,那么这个时候我们无法保证两个Activity中的ApiService是同一个。其实大家翻翻Dagger的源码就会发现,Dagger的单例模式必须要保证是同一个@Component注释的类。
我们先看这样的一个例子,我们把访问网络的类CallNets设置为单例模式
这个是ApiService类,他里面有一个CallNets类,这个类是单例模式。
package com.example.daggertest2;
import android.util.Log;
public class ApiService {
private CallNets callNets;
public ApiService(CallNets callNets) {
this.callNets = callNets;
}
public void register() {
Log.i("zhang_xin", "apiService注册成功");
}
}
CallNets类,实际开发中可能是OkhttpClient等。
package com.example.daggertest2;
public class CallNets {
//访问网络的逻辑
}
CallNetsModule类,方法我们注解成单例模式
package com.example.daggertest2;
import android.util.Log;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class CallNetsModule {
@Singleton
@Provides
public CallNets getCallNets(){
CallNets callNets=new CallNets();
Log.i("zhang_xin",callNets.toString());
return callNets;
}
}
接下来我们创建了两个@Component注解的类
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules=UserModule.class)
public interface LoginComponet {
void inject(LoginActivity activity);
}
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = UserModule.class)
public interface UserComponet {
void inject(MainActivity activity);
}
UserModule和UserManager
package com.example.daggertest2;
public class UserManager {
private ApiService apiService;
public UserManager(ApiService apiService){
this.apiService=apiService;
}
public void register(){
apiService.register();
}
}
package com.example.daggertest2;
import dagger.Module;
import dagger.Provides;
@Module(includes = {CallNetsModule.class})
public class UserModule {
@Provides
public ApiService getApiService(CallNets callNets){
return new ApiService(callNets);
}
@Provides
public UserManager getUserManager(ApiService apiService){
return new UserManager(apiService);
}
}
两个Activity
package com.example.daggertest2;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().userModule(new UserModule()).callNetsModule(new CallNetsModule()).build().inject(this);
userManager.register();
startActivity(new Intent(this,LoginActivity.class));
}
}
package com.example.daggertest2;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class LoginActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
DaggerLoginComponet.builder().userModule(new UserModule()).callNetsModule(new CallNetsModule()).build().inject(this);
userManager.register();
}
}
我们看下打印输出
/zhang_xin: com.example.daggertest2.CallNets@b45757d /zhang_xin: apiService注册成功 /zhang_xin: com.example.daggertest2.CallNets@eea8d0f /zhang_xin: apiService注册成功
很明显,两个CallNets不是同一个对象,我们虽然标注了@Singleton,但因为创建了两个Componet,所以得到的是两个不同的CallNets对象。
接下来我们就解决这个问题。
我们需要创建一个最高级别的Component
首先我们把CallNetsModule中无法提供单例的方法注释掉
package com.example.daggertest2;
import android.util.Log;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class CallNetsModule {
// @Singleton
// @Provides
// public CallNets getCallNets(){
// CallNets callNets=new CallNets();
// Log.i("zhang_xin",callNets.toString());
// return callNets;
// }
}
然后我们创建AppComponet和AppModule
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = AppModule.class)
public interface AppComponet {
//这里不需要提供inject方法,因为我们不需要注入,是依附于其它的Conmponent
}
我们在AppModule类中提供CallNets的单例
import android.util.Log;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AppModule {
@Singleton
@Provides
public CallNets getCallNets(){
CallNets callNets=new CallNets();
Log.i("zhang_xin",callNets.toString());
return callNets;
}
}
然后修改LoginComponent UserComponent
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
/**
* 1,在这里我解释下,我们的UserModule并没有提供CallNets实例,如果Dagger在UserModule中没有发现CallNets实例
* 他就会去依赖既AppComponet.class里面去找.
* 2,这里不能有@Singleton注释,因为Component的dependencies与Component
* 自身的scope不能相同
*/
@Component(modules=UserModule.class,dependencies = AppComponet.class)
public interface LoginComponet {
void inject(LoginActivity activity);
}
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
/**
* 2,这里不能有@Singleton注释,因为Component的dependencies与Component
* 自身的scope不能相同
*/
@Component(modules = UserModule.class,dependencies = AppComponet.class)
public interface UserComponet {
void inject(MainActivity activity);
}
这里我做下说明
dagger1.ng.png
注意第五点,所以我们没办法给LoginComponent和AppComponent添加@Singleton注释,既然没办法添加@Singleton注释,那么我们该怎么给LoginComponent和AppComponent添加注释呢?因为Dagger给我们提供的注释只有@Singleton,所以需要我们自己定义注释。
package com.example.daggertest2;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import javax.inject.Scope;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Scope
@Documented
@Retention(RUNTIME)
public @interface ActivityScope {
}
@scope注明是Scope
@documented标记在文档
@Retention 级别,有source class runtime
然后我们修改LoginComponent和UserComponent文件,添加@ActivityScope 注释。
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
/**
* 1,在这里我解释下,我们的UserModule并没有提供CallNets实例,如果Dagger在UserModule中没有发现CallNets实例
* 他就会去依赖既AppComponet.class里面去找.
* 2,这里不能有@Singleton注释,因为Component的dependencies与Component
* 自身的scope不能相同
*/
@ActivityScope//添加该注释
@Component(modules=UserModule.class,dependencies = AppComponet.class)
public interface LoginComponet {
void inject(LoginActivity activity);
}
package com.example.daggertest2;
import dagger.Component;
/**
* 2,这里不能有@Singleton注释,因为Component的dependencies与Component
* 自身的scope不能相同
*/
@ActivityScope//添加该注释
@Component(modules = UserModule.class,dependencies = AppComponet.class)
public interface UserComponet {
void inject(MainActivity activity);
}
然后修改AppComponent类
package com.example.daggertest2;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = AppModule.class)
public interface AppComponet {
Conmponent
CallNets getCallNets();
}
在这里我们做一个桥接,这里的CallNets对象就是由AppModule提供的。
我们现在reBuild工程,已经可以了没有报错
可是我们现在又面临一个问题,接下来我们该怎样在LoginActivity和MainActivity中使用AppComponent呢?
DaggerUserComponet.builder().userModule(new UserModule()).appComponet();
我们可以看到appComponent()需要传入AppComponet类型的对象,在这里我们怎么给appComponent()传入参数呢?
因为Singleton是application级别的,所以我们需要在Application中将AppComponent实例化。创建MyApplication继承Application。
package com.example.daggertest2;
import android.app.Application;
import android.util.Log;
public class MyApplication extends Application {
private AppComponet appComponet;
@Override
public void onCreate() {
super.onCreate();
appComponet= DaggerAppComponet.create();
}
public AppComponet getAppComponet() {
return appComponet;
}
}
然后我们就可以在MainActivity 和LoginActivity里调用了
package com.example.daggertest2;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerUserComponet.builder().userModule(new UserModule())
.appComponet(((MyApplication) getApplication())
.getAppComponet()).build().inject(this);
userManager.register();
startActivity(new Intent(this, LoginActivity.class));
}
}
package com.example.daggertest2;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class LoginActivity extends AppCompatActivity {
@Inject
UserManager userManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
DaggerLoginComponet.builder().userModule(new UserModule())
.appComponet(((MyApplication) getApplication())
.getAppComponet()).build().inject(this);
userManager.register();
}
}
这样我们就实现了单例模式
我们在ApiService中添加打印数据,测试下是不是单例模式
package com.example.daggertest2;
import android.util.Log;
public class ApiService {
private CallNets callNets;
public ApiService(CallNets callNets) {
this.callNets = callNets;
}
public void register() {
Log.i("zhang_xin", "apiService注册成功"+this.callNets.toString());
}
}
看下打印结果
10-24 16:22:59.691 2967-2967/com.example.daggertest2 I/zhang_xin: apiService注册成功com.example.daggertest2.CallNets@4a7ac880
10-24 16:22:59.701 2967-2967/com.example.daggertest2 I/zhang_xin: apiService注册成功com.example.daggertest2.CallNets@4a7ac880
OK,大功告成!
第九部分:SubComponent
这里我就强调两点
1,SubComponent同时具备两种不同生命周期的scope,Subcomponent具备了父Component的scope,也具备自己的Scope
2,subComponent的Scope范围小于父Component
网友评论