Dagger2分析学习
来源:互联网 发布:如何做好站内优化 编辑:程序博客网 时间:2024/06/06 03:56
Dagger学习笔记
1.概要
Dagger是为Android和Java平台提供的一个完全静态的,在编译时进行依赖注入的框架,原来是由Square公司维护的然后现在把这堆东西扔给
Google维护了
控制反转(Inversion of Control,缩写Ioc),是面向对象编程中的一种设计原则,可以用来减少计算机代码之间的耦合度,其中最常见的方式是依赖注入
(Dependency Injection),还有一种叫做“依赖查找”(Dependency Lookup),通过控制反转对象在创建的时候,有控制系统内所有对象的外界实体,将其
所有依赖的对象的引用传递给它,也可以说,依赖注入到对象中。
应用Dagger2的依赖库:
项目根目录的配置文件中配置:
buildscript { dependencies { classpath 'com.android.tools.build:gradle:2.2.2' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' (annotation processing tools)//注解处理工具
主要是用在java编译的过程中解析java文件中的注解类型,从而产生代码来替换掉源码中的注解的功能。 }}
//应用apt插件apply plugin: 'com.neenbedankt.android-apt'dependencies { compile 'com.google.dagger:dagger:2.4' apt 'com.google.dagger:dagger-compiler:2.4' provided 'org.glassfish:javax.annotation:10.0-b28'}
依赖注入的三种方式:
public class CoffeeMachinWithInjection implements InjectMaker{ private CoffeeMaker maker; /*依赖注入的3种常见形式 *No.1 构造函数注入 */ public CoffeeMachinWithInjection(CoffeeMaker maker){ this.maker = maker; } //No.2 Setter注入 public void setMaker(CoffeeMaker maker){ this.maker = maker; } // //No.3 接口注入 @Override public void injectMaker(CoffeeMaker maker) { this.maker = maker; } public String makeCoffee(){ return maker.makeCoffee(); }}上述的表示中我们在平时的代码开发中常使用到的代码开发方式,手动提供注入,解决了使用在类内部使用时new一个新的对象。下面我们看是来对
Dagger2进一步使用讲解。动态的解决掉依赖注入。
在Dagger中我们有六种注解:
1.Inject:两个作用
1.在宿主中表明需要注入的类
2.在需要实例化的类中的构造方法上使用,表明需要注解(没有构造参数的类上号使用,在有构造参数的类中需要使用在module中使用@provides提供)
2.Component:主要是在产生依赖的类之间生成通信的桥梁
3.module:专门用来提供依赖
4.provides:用来在module中专门提供产生依赖的类,主要用来标记提供依赖的方法
这里再说明一个问题,我们有两种方式可以提供依赖,一个是注解了@Inject的构造方法,一个是在Module里提供的依赖,那么Dagger2是怎么选择依赖提供的呢,规则是这样的:
- 步骤1:查找Module中是否存在创建该类的方法。
- 步骤2:若存在创建类方法,查看该方法是否存在参数
- 步骤2.1:若存在参数,则按从步骤1开始依次初始化每个参数
- 步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
步骤3:若不存在创建类方法,则查找Inject注解的构造函数,看构造函数是否存在参数
2.dagger2调用过程
dagger2的调用流程如上图所示:
Dagger2有三个构建组成:从上到下依次为:
1.依赖需求方(宿主),需要使用对象实例的类。
2.依赖提供方,统一提供实例类型或数据掉用的类。
3.依赖注入构件(Component),负责管理module产生的数据注入到宿主中,在编程中表现为一个接口,编译时apt自动回生成一个以Dagger开头的类。
上图中从上到下依次对应上述的三个部分。下面先分析上面代码的表现形式:
在Activity中得到LoginActivityComponont:
DaggerLoginActivityComponont.builder() .appComponent(AppGlobalState.getInstances().getComponent()) .loginModule(new LoginModule(this, this)) .volidateModule(new VolidateModule()) .build() .inject(this);LoginActivity中使用inject(this)方法来获取建立与依赖注解类相关联。
先查看一下LoginActivityComponont类的实现:
/** * Created by cangck on 17/5/19. */@MainActivityScope@Component(modules = {LoginModule.class, VolidateModule.class}, dependencies = AppComponent.class)public interface LoginActivityComponont { LoginActivity inject(LoginActivity activity);}
在这个类中我们使用到了的注解说明:@MainActivityScope
@Scope@Retention(RetentionPolicy.RUNTIME)public @interface MainActivityScope {}
@scope又是Dagger2的一个域修饰符,对对象提供的范围的一个限制
@Target(ANNOTATION_TYPE)@Retention(RUNTIME)@Documentedpublic @interface Scope {}@Singleton实例表示时,单例返回
@Modulepublic class AppModule { private Application mApplication; public AppModule(Application application) { this.mApplication = application; } @Singleton @Provides public Application provideApplication() { return mApplication; }}
LoginModule的实现
@Modulepublic class LoginModule { private LoginActivity mActivity; private ILoginView mLoginView; public LoginModule(LoginActivity activity, ILoginView loginView) { this.mActivity = activity; this.mLoginView = loginView; } @Provides public LoginActivity providesActivity() { return mActivity; } @Provides public ILoginView proivdeLoginView() { return mLoginView; } @MainActivityScope @Provides public LoginUserBean getUserData() { LoginUserBean userBean = new LoginUserBean(); userBean.setName("cck"); userBean.setAge(20); return userBean; } @Provides public LoginPresenter provideLoginPresenter(LoginActivity activity, ILoginView loginView) { LoginPresenter presenter = new LoginPresenter(activity, loginView); return presenter; }}
@MainActivityScope这个注解是对@Scope的扩展,表示只用在Component组件上使用@MainActivityScope注解是才能调用getUserData方法
- component 的 inject 函数不要声明基类参数;
- Scope 注解必须用在 module 的 provide 方法上,否则并不能达到局部单例的效果;
- 如果 module 的 provide 方法使用了 scope 注解,那么 component 就必须使用同一个注解,否则编译会失败;
- 如果 module 的 provide 方法没有使用 scope 注解,那么 component 和 module 是否加注解都无关紧要,可以通过编译,但是没有局部单例效果;
- 对于直接使用 @Inject 构造函数的依赖,如果把 scope 注解放到它的类上,而不是构造函数上,就能达到局部单例的效果了;
@Provides public ILoginView proivdeLoginView() { return mLoginView; } @Provides public LoginUserBean getUserData() { LoginUserBean userBean = new LoginUserBean(); userBean.setName("cck"); userBean.setAge(20); return userBean; }上面代码中使用@provides注解方法,当调用对象时,注解工具会在在方法中查找使用@provides注解的方法,并且根据返回值来确认是通过那个方法来提供数据。
注:方法的调用使用过返回值来确认的
下列类为VolidateModule的实现
/** * Created by cangck on 17/5/19. */@Modulepublic class VolidateModule {}先列举上面的两个类来作为使用说明就Ok了
我们先观察一下LoginActivityComponont类上我们使用了注解
@MainActivityScope@Component(modules = {LoginModule.class, VolidateModule.class}, dependencies = AppComponent.class)
在上面已经介绍过了LoginActivityComponont类使用了注解@Component之后就好变成了Dagger2中的组件控制器。在观察上图,
@Component的注解参数:1.modules,2.dependencies
1.modules表示当前的Component管理LoginModule,VolidateModule,当需要使用类实例时当前的Component只能从上述的两个类的范围中来查找,不会到其他的类中去找。
2.dependencies:相当于类的继承关系,当前的Component不仅可以从自己管理的类中类获取对象,亦可以使用AppComponent提供的方法来使用。
Dagger2之间的三个组件关联的方式已经介绍完成:
1.LoginActivity中使用inject(this)的方法和Dagger2中的组件Component建立关系。
2.Component与module建立联系是通过@Component(moudel={aModule.class,BModule.class},dependecies=DComponent.class)
4.Component的声明周期:
1.创建Component实例
DaggerLoginActivityComponont.builder() .appComponent(AppGlobalState.getInstances().getComponent()) .loginModule(new LoginModule(this, this)) .volidateModule(new VolidateModule()) .build() .inject(this);
- onCreate()方法调用完成后,Component实例就会因为没有被引用而被垃圾回收器回收.其中传入给Component实例的Module实例也会一同被回收,这也就能说明不同的Component实例之间是没有联系的(Component依赖除外).这里需要注意的是,使用Lazy和Provider时,与该依赖对象有关的Module实例会被Lazy和Provider引用,所以该Module实例不会被垃圾回收器回收
Dagger2 入门,以初学者角度. Dagger2 入门,以初学者角度.
依赖注入神器:Dagger2详解系列
图文教程
Android常用开源工具(2)-Dagger2进阶
Dagger2 Scope 注解能保证依赖在 component 生命周期内的单例性吗?
demo
Android:dagger2让你爱不释手-重点概念讲解、融合篇
- Dagger2分析学习
- dagger2 学习
- dagger2学习
- Dagger2依赖关系分析
- Dagger2代码分析
- Dagger2 原理分析
- Dagger2学习笔记
- Dagger2 学习笔记
- Dagger2 学习(1)
- Dagger2 学习(2)
- dagger2深入学习
- Dagger2 学习笔记
- Dagger2 生成代码学习
- Dagger2的学习笔记
- Dagger2学习网址参考
- Dagger2的学习过程
- Dagger2学习总结
- Dagger2 学习与理解
- Android Assets下文件复制到sdcard
- 页面前端的水有多深?再议页面开发
- Binder学习笔记
- phpize是什么
- nio框架中的多个Selector结构
- Dagger2分析学习
- Java入侵检测(二)
- js数组去重的几种方法总结
- 数据通信协议的简介(数据通信协议和网络协议有什么区别?)
- 浅谈对ActiveMQ的理解
- 2017-05-19 DBA日记,记一次SQL语句诊断的过程[之前的标题有误,现修改]
- CAS单点登录
- 阿里云服务器ssh连不上,可以ping通
- HDU 2844 Coins——多重背包