Dagger2基础 (一)

一、 Dagger2 的使用场景
相信大家在使用Android MVP 框架时,一定对dagger2 不陌生。可能在自己的项目中使用,却不是十分明白为什么要这样使用。下面来谈谈我对dagger2的一点理解吧!
1、Dagger2是什么,有什么作用?
Dagger2 (“A fast dependency injector for Android and Java”) 是一个提供给Android 和Java使用的快速依赖注射器;是一个基于JSR-300标准的依赖注入框架,在编译期间自动生成代码,负责依赖对象的创建。
2、使用Dagger2有哪些好处?
在预编译期间生成代码完成依赖注入,进一步解耦,提高代码的健壮性和可维护性。
举个例子:

 public class MainActivity extends AppCompatActivity{
 
    LoginActivityPresenter presenter;
     
    protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
     
        OkHttpClient okHttpClient = new OkHttpClient();
        RestAdapter.Builder builder = new RestAdapter.Builder();
        builder.setClient(new OkClient(okHttpClient));
        RestAdapter restAdapter = builder.build();
        ApiService apiService = restAdapter.create(ApiService.class);
        UserManager userManager = UserManager.getInstance(apiService);
       
        //Presenter is initialized here
        presenter = new LoginActivityPresenter(this, userManager);
   }
}

其实我们需要的只是LoginActivityPresenter对象,但是因为使用依赖注入的原因,我们不得不在LoginActivity中初始化一大堆Presenter所需要的依赖。

现在不仅依赖于LoginActivityPresenter,还依赖OkHttpClient ,RestAdapter等。它们之中任何一个的构造改变了,或者Presenter构造改变了,我们都需要反复修改LoginActivity中的代码。

而Dagger框架就解决了这种问题,使用dagger2框架后相同代码如下:

 public class MainActivity extends AppCompatActivity{
    @Inject
    LoginActivityPresenter presenter;
     
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
    
        //Satisfy all dependencies requested by @Inject annotation
        getDependenciesGraph().inject(this);
   }
}

LoginActivity瞬间清爽了。dagger2框架可以让依赖注入独立于组件之外,不管Presenter的依赖怎么改,都不会对LoginActivity的代码照成任何影响,这就是dagger2框架的好处了。

二、Dagger2的使用

1、注解

Dagger2 通过注解来生成代码,定义不同的角色,主要的注解如下:
@Module: Module类里面的方法专门提供依赖,所以我们定义一个类,用@Module注解,这样Dagger在构造类的实例的时候,就知道从哪里去找到需要的依赖。
**@Provides: **在Module中,我们定义的方法是用这个注解,以此来告诉Dagger我们想要构造对象并提供这些依赖。
**@Inject: **通常在需要依赖的地方使用这个注解。换句话说,你用它告诉Dagger这个类或者字段需要依赖注入。这样,Dagger就会构造一个这个类的实例并满足他们的依赖。
**@Component: **Component从根本上来说就是一个注入器,也可以说是@Inject和@Module的桥梁,它的主要作用就是连接这两个部分。将Module中产生的依赖对象自动注入到需要依赖实例的Container中。
@Scope: Dagger2可以通过自定义注解限定注解作用域,来管理每个对象实例的生命周期。
**@Qualifier: **当类的类型不足以鉴别一个依赖的时候,我们就可以使用这个注解标示。例如:在Android中,我们会需要不同类型的context,所以我们就可以定义 qualifier注解“@perApp”和“@perActivity”,这样当注入一个context的时候,我们就可以告诉 Dagger我们想要哪种类型的context。

2、结构
Dagger2要实现一个完整的依赖注入,必不可少的元素有三种:Module,Component, Container。
图片1
为了便于理解,其实可以把component想象成针管,module是注射瓶,里面的依赖对象是注入的药水,build方法是插进患者(Container),inject方法的调用是推动活塞。

3、项目依赖
Android Gradle在这里插入图片描述
三、Demo 例子
1、@Inject和@Component
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
@Inject注解只是JSR-330中定义的注解,在javax.inject包中。
这个注解本身并没有作用,它需要依赖于注入框架才具有意义,用来标记需要被注入框架注入的方法,属性,构造。

而Dagger2则是用Component来完成依赖注入的,@Component可以说是Dagger2中最重要的一个注解。命名方式推荐为:目标类名+Component,在编译后Dagger2就会为我们生成DaggerXXXComponent这个类,它是我们定义的xxxComponent的实现,在目标类中使用它就可以实现依赖注入了。

2、@Moudel
在这里插入图片描述
实现 Component
在这里插入图片描述
实现Container
A就是可以被注入依赖关系的容器。
在这里插入图片描述
@Module需要和@Provide是需要一起使用的时候才具有作用的,并且@Component也需要指定了该Module的时候。
@Component可以指定多个@Module的,如果需要提供多个依赖的话。
并且Component也可以依赖其它Component存在。添加多个Module有两种方法,一种是在Component的注解@Component(modules={××××,×××})中添加多个modules
在这里插入图片描述
另外一种添加多个Module的方法可以使用@Module的 includes的方法(includes={××××,×××})
在这里插入图片描述
3、@Qualifier和@Named
@Qualifier是限定符,而@Named则是基于String的限定符
当我有两个相同的依赖(都继承某一个父类或者都是先某一个接口)可以提供给高层时,那么程序就不知道我们到底要提供哪一个依赖,因为它找到了两个。
这时候我们就可以通过限定符为两个依赖分别打上标记,指定提供某个依赖。
在这里插入图片描述
我们是通过@Inject Pot的构造器注入Flower依赖的,在这里可以用到限定符。
在这里插入图片描述
在这里插入图片描述
更常用的方法是使用注解@Qualifier来自定义注解。
在这里插入图片描述
4、@Component的dependence
上面也说过,Component可以依赖于其他Component,可以使用@Component的dependence,也可以使用@SubComponent,这样就可以获取其他Component的依赖了。

如:我们也用Component来管理FlowerModule和PotModule,并且使用dependence联系各个Component。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
PotModule需要依赖Flower,需要指定其中一个子类实现,这里使用RoseFlower
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
而在MainActivity则需要创建其依赖的Component
在这里插入图片描述
5、单例使用
创建某些对象有时候是耗时、浪费资源的或者需要确保其唯一性,这时就需要使用@Singleton注解标注为单例了。
在这里插入图片描述
※注意:Java中,单例通常保存在一个静态域中,这样的单例往往要等到虚拟机关闭时候,该单例所占用的资源才释放。但是,Dagger通过注解创建出来的单例并不保持在静态域上,而是保留在Component实例中。所以说不同的Component实例提供的对象是不同的。

自定义Scope
@Singleton就是一种Scope注解,也是Dagger2唯一自带的Scope注解,下面是@Singleton的源码
在这里插入图片描述
可以看到定义一个Scope注解,必须添加以下三部分:
@Scope :注明是Scope
@Documented :标记文档提示
@Retention(RUNTIME) :运行时级别
对于Android,我们通常会定义一个针对整个APP全生命周期的@PerApp的Scope注解和针对一个Activity生命周期的@PerActivity注解,如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
@PerActivity的使用例:
在这里插入图片描述
在这里插入图片描述
通过上面的例子可以发现,使用自定义Scope可以很容易区分单例的有效范围。

最后
以上就是Dagger2常见的一些用法,由于自己也是边学边用,难免有错误的地方 ,希望及时指出。有时间的话,还是推荐大家去读读Dagger2的源码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值