dagger2学习
来源:互联网 发布:信仰的定义知乎 编辑:程序博客网 时间:2024/05/16 14:52
最近在学习单元测试的过程中,学习一下使用dagger2来做依赖注入
在介绍dagger2
的使用前,先来介绍一下DL
的几种方式。
- set方法
- 将依赖作为参数
- 将依赖作为构造方法的参数传入(推荐使用这种方式)
下面重点介绍dagger2的使用
1.定义
Module
:Dependency
生产工厂
一个Module
对应代码中的一个类,同时为了表示这是一个Module,而不是一个简单的类,需要添加dagger2
里面的一个annotation @Module
来进行标识,之所以说Module
是一个生产dependency
的工厂,是因为Module
中有很多方法,而这些方法主要是创建dependency
,但是一个Module
就是一个类,他里面也有正常的方法,而为了区别哪些是用来创建dependency
的方法,需要用dagger2
里面的一个annotation @Provides
来加以区分。具体实例代码如下:
@Modulepublic class AppModule { @Provides public LoginPresenter provideLoginPresenter(UserManager userManager){ return new LoginPresenter(userManager); } @Provides public UserManager provideUserManager(){ return new UserManager(); } @Provides public PassWordValidator providePassWordValidator(){ return new PassWordValidator(); }}
例如创建一个LoginPresenter
对象,会先到module
中寻找Loginpresenter
的provide
方法,这时发现创建LoginPresenter
对象需要传入一个UserManager
对象,就会在Module
中继续寻找UserManager
的Provide
方法,再调用LoginPresenter
的Provide
方法创建LoginPresenter
对象
Component
:Dependency
生产工厂管理员
Component
是一个接口,和Module
需要使用@Module
一样,也是需要使用@Component
来修饰,表示这是一个dagger2
的Component
,实际使用中,由于有多个Module
以及Component
,我们需要告知Component
去哪些Module
中寻找Provide
方法,这时我们的Component
就可以定义为:
@Component(modules = {AppModule.class}) //<= public interface AppComponent {}
其中modules
属性接收一个数组,里面是这个Component
管理的所有Module
2.使用
方法一:在Component
中定义一个Dependency
的返回方法
例如我们需要一个Loginpresenter
,我们就可以在Component
中定义一个Loginpresenter
的返回方法,如下:
@Component(modules = {AppModule.class})public interface AppComponent { LoginPresenter loginPresenter();}
了解完使用方法以后,我们来了解一下dagger2
的工作原理,在你的java
代码编译成字节码的过程中,dagger2
会对所有的Component
(就是用 @Component
修饰过的interface
进行处理,自动生成一个实现了这个interface
的类,生成的类名是Component
的名字前面加上Dagger
,比如我们定义的 AppComponent
,对应的自动生成的类叫做DaggerAppComponent
。我们知道,实现一个interface
需要实现里面的所有方法,因此,DaggerAppComponent
是实现了 loginPresenter()
这个方法的。实现的方式大致就是从 AppComponent
管理的 AppModule
里面去找LoginPresenter
的Provider
方法,然后调用这个方法,返回一个LoginPresenter
因此,使用这种方式,当Client
需要Dependency
的时候,首先需要用DaggerAppComponent
这个类创建一个对象,然后调用这个对象的loginPresenter()
方法,这样Client
就能获得一个LoginPresenter
了,这个DaggerAppComponent
对象的创建及使用方式如下:
public class MainActivity extends AppCompatActivity { LoginPresenter mLoginPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); AppComponent appComponent = DaggerAppComponent.builder().appModule(new AppModule()).build(); LoginPresenter presenter = appComponent.loginPresenter(); }}
方法二:使用Field Injection
使用这种方式的做法是,我们就在LoginActivity
里面定义一个LoginPresenter
的field
,这个field
需要使用@Inject
修饰一下,然后在onCreate()
里面,我们把DaggerAppComponent
对象创建出来,调用这个对象的inject
方法,把LoginActivity
传进去
public class LoginActivity extends AppCompatActivity { @Inject LoginPresenter mLoginPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); AppComponent appComponent = DaggerAppComponent.builder().appModule(new AppModule()).build(); appComponent.inject(this); }}
当然,我们需要先在AppComponent
里面定义一个inject(LoginActivity loginActivity)
方法:
@Component(modules = {AppModule.class})public interface AppComponent { void inject(LoginActivity loginActivity);}
需要注意的是,@Inject field
不能使用private
,不然dagger2
找不到这个field
。不过,需要注意的一点是,这种方式不支持继承,比如说LoginActivity
继承自一个 BaseActivity
,而@Inject StatManager mStatManager
是放在BaseActivity
里面的,那么在LoginActivity
里面调用 appComponent.inject(this)
,并不会让BaseActivity
里面的 mStatManager
得到实例化,你必须在 BaseActivity
里面也调用一次appComponent.inject(this)
;
其他注解标识@Singleton
和Constructor Injection
如果每次Client
向Component
索要一个Dependency
,Component
都会创建一个新的出来,这可能会导致资源的浪费,或者说很多时候不是我们想要的,比如说,SharedPreferences
、UserManager
、OkHttpClient
, Retrofit
这些都只需要一份就好了,不需要每次都创建一个instance
,这个时候我们可以给这些Dependency
的Provider
方法加上@Singleton
就好了
@Modulepublic class AppModule { @Provides @Singleton public OkHttpClient provideOkHttpClient() { OkHttpClient okhttpClient = new OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .build(); return okhttpClient; }}
其实AppModule
里面的很多Provider
方法是不需要定义的。比如说在这种情况下,LoginPresenter
的Provider
方法 provideLoginPresenter(UserManager userManager)
就不需要定义,你只需要在定义LoginPresenter
的时候,给它的Constructor
加上 @Inject
修饰一下,这也就是我们现在要讨论的Constructor Injection
:
public class LoginPresenter { UserManager mUserManager; @Inject public LoginPresenter(UserManager userManager) { mUserManager = userManager; } public void login(String name, String pwd){ if (name==null||name.length()==0){return;} if (pwd==null||pwd.length()==0){return;} mUserManager.performLogin(name,pwd); }}
dagger2
会自动创建这个LoginPresenter
所需要的Dependency
,所以会去Module
里面找到这个LoginPresenter
所需的Dependency
,交给LoginPresenter
的Constructor
,创建好这Dependency
,交给Client
,同理我们也不需要提供UserManager
的Provider
方法,只需要在它的构造方法上添加@Inject
。说白了,你只需要给那些不是通过Constructor
来创建的Dependency
(比如说SharedPreferences
、UserApiService
等)定义Provider
方法。
参考文章
使用dagger2来做依赖注入,以及在单元测试中的应用
阅读全文
0 0
- dagger2 学习
- dagger2学习
- Dagger2学习笔记
- Dagger2 学习笔记
- Dagger2 学习(1)
- Dagger2 学习(2)
- dagger2深入学习
- Dagger2 学习笔记
- Dagger2 生成代码学习
- Dagger2的学习笔记
- Dagger2学习网址参考
- Dagger2的学习过程
- Dagger2学习总结
- Dagger2分析学习
- Dagger2 学习与理解
- Dagger2学习笔记
- dagger2学习笔记
- Dagger2学习笔记(一)
- Linux : rc.local 重启不生效
- 解决eclipse编译时报内存不足问题
- Map和List使用区别
- Quartz(二) quartz测试
- 光环国际PMP:看完你就知道什么是瞎忙与高效
- dagger2学习
- hdu 6216 A Cubic number and A Cubic Number
- Java并发编程:volatile关键字解析
- StratoIO WebPrinter 是什么?StratoIO WebPrinter实现打印的过程,StratoIO WebPrinter Javascript API
- CDH 安装spark后,spark-shell启动报错
- Iterator遍历器删除集合中元素抛异常
- 使用Anaconda与pip报错'_NamespacePath' object has no attribute 'sort'的解决方法
- 计蒜客 16957 Skiing(2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 H)
- SparkStream:4)foreachRDD详解