Dagger——Android 的依赖注入框架

简介

在开发程序的时候,会用到各种对象,很多对象在使用之前都需要进行初始化。例如你要操作一个SharedPreference,你需要调用getSharedPreferences(String name,int mode)来获取一个对象,然后才能使用它。而如果这个对象会在多个Activity中被使用,你就需要在每个使用的场景中都写下同样的代码。这不仅麻烦,而且增加了出错的可能。dagger的用途就是:让你不需要初始化对象。换句话说,任何对象声明完了就能直接用。

原理

dagger是使用依赖注入的方式,使用Annotation给需要注入的对象做标记,通过inject()方法自动注入所有对象,从而完成自动的初始化。 示例代码:

public class MainActivity extends Activity {
    // 通过@Inject对对象进行标记
    @Inject SharedPreferences sharedPreferences;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 注入依赖
        ObjectGraph.create(AppModule.class).inject(this);

        // 获取name的值并输出
        System.out.println(sharedPreferences.getString("name", ""));
    }
}

依赖注入(Dependency Injection):在类A中要用到一个B的对象(依赖),需要通过新建B的实例或其他一些主动的方式来获取对象,然后才能调用。而通过外部的方式自动将B的对象分配给A(注入),实现相对被动的获取对象,这个过程称为依赖注入。希望更多了解依赖注入可以自行Google。

使用方式

以一个简单的“老板和程序员”App为例。你想实现Boss对象的自动注入,那么首先你要告诉程序它要怎么初始化一个Boss。在dagger中,为Boss类的构造方法添加一个@Inject注解,程序就会在需要的时候找到这个被标记的构造方法并调用它,从而获取一个Boss对象。

public class Boss {
    ...

    @Inject
    public Boss() {
        ...
    }

    ...
}

需要注意的是,如果构造函数含有参数,Dagger会在构造对象的时候先去获取这些参数(不然谁来传参?),所以你要保证这些参数的构造方法也有@Inject标记,或者能够通过@Provides注解(下面会介绍)来获取到。

然后,在声明Boss对象的时候,在前面同样添加@Inject注解。程序会在依赖注入的过程中自动初始化被注解的对象。

public class MainActivity extends Activity {
    @Inject Boss boss;
    ...
}

最后,创建ObjectGraph类并执行inject()方法并将当前MainActivity作为参数传入,Boss的对象就被注入到了MainActivity中。

public class MainActivity extends Activity {
    @Inject Boss boss;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ObjectGraph.create(AppModule.class).inject(this);
    }
    ...
}

到此为止,使用Dagger将一个Boss对象注入到MainActivity的流程就完成了。上面这段代码中出现了两个类:ObjectGraph和AppModule。其中ObjectGraph是由Dagger提供的类,可以简单理解为一个工具类,它的create函数中参数为所有的Module,本文不详述,如果有兴趣可以跟进我之后的Dagger详解。AppModule是一个自定义类,代码如下:

@Module(injects = MainActivity.class)
public class AppModule {
}

可以看到,AppModule是一个空类,只有一行注解。@Module注解表示,这个类是一个Module,Module的作用是提供信息,让ObjectGraph知道应该怎样注入所有的依赖。例如,上面这段代码中声明了可注入对象的信息:MainActivity.class(使用显式声明这样的看起来很麻烦、多此一举的方式和Dagger的原理有关,本文不详述)。

自定义依赖

对构造方法进行注解是很好用的实现依赖的途径,然而它并不适用于所有情况。

接口(Interface)是没有构造方法的
第三方库提供的类,它们的构造方法不能被注解
有些类需要灵活选择初始化的配置,而不是使用一个单一的构造方法
对于这样的情况,可以使用@Provides注解来提供专用的初始化方法,实现自定义依赖。

**@Provides
Coder provideCoder(Boss boss) {

return new Coder(boss);

}**
同样,@Provides注解的方法如果含有参数,它的所有参数也要保证能够被Dagger获取到。

所有带有@Provides注解的方法都需要被封装到带有@Module注解的类中:

**@Module
public class AppModule {

@Provides
Coder provideCoder(Boss boss) {
    return new Coder(boss);
}

}**
单例

Dagger支持单例,实现方式也十分简单:

**// @Inject注解构造方法的单例模式
@Singleton
public class Boss {

...

@Inject
public Boss() {
    ...
}

...

}
// @Provides注解提供初始化方法的单例模式
@Provides
@Singleton
Coder provideCoder(Boss boss) {

return new Coder(boss);

}**
通过上面的方法添加@Singleton注解之后,对象只会被初始化一次,之后的每次都会被直接注入相同的对象。

Qualifier(限定符)

如果有两类程序员,他们的能力值power分别是5和1000,应该怎样让Dagger对他们做出区分呢?使用@Qualifier注解

首先,创建一个@interface:

@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Level {
  String value() default "";
}

然后,为这两类程序员分别设置@Provides方法,并使用@Qualifier对他们做出不同的标记:

@Provides @Level("low") Coder provideLowLevelCoder() {
    Coder coder = new Coder();
    coder.setName("战五渣");
    coder.setPower(5);
    return coder;
}

@Provides @Level("high") Coder provideHighLevelCoder() {
    Coder coder = new Coder();
    coder.setName("大神");
    coder.setPower(1000);
    return coder;
}

最后,在使用的时候也用上相应的@Qualifier注解。

@Inject @Level("low") Coder lowLevelCoder;
@Inject @Level("high") Coder highLevelCoder;

编译时检查

实质上,Dagger会在编译时对代码进行检查,并在检查不通过的时候报编译错误(为什么?这和Dagger的原理有关,有兴趣的话可以关注我之后发布的Dagger详解)。检查内容主要有三点:

  • 所有含有依赖注入的类,需要被显式 声明在相应的Module中。
  • 一个Module中所有@Provides方法的参数都必须在这个Module种提供相应的@Provides方法,或者在@Module注解后添加“complete = false”注明这是一个不完整Module(即它会被其他Module所扩展)。
  • 一个Module中所有的@Provides方法都要被它声明的注入对象所使用,或者在@Module注解后添加“library = ture”注明(即它是为了扩展其他Module而存在的)。
时间: 2024-10-25 02:25:08

Dagger——Android 的依赖注入框架的相关文章

[Android]使用Dagger 2进行依赖注入 - Producers(翻译)

以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/6234811.html 使用Dagger 2进行依赖注入 - Producers 原文:http://frogermcs.github.io/dependency-injection-with-dagger-2-producers/ 本文是在Android中使用Dagger 2框架进行依赖注入的系列文章中的一部分.今天我们将探索下Dagger Producers

用 Dagger 2 实现依赖注入

本文讲的是用 Dagger 2 实现依赖注入, 原文地址:Dependency Injection with Dagger 2 原文作者:CodePath 译文出自:掘金翻译计划 译者: tanglie1993 校对者:mnikn, Zhiw 用 Dagger 2 实现依赖注入 概要 很多 Android 应用依赖于一些含有其它依赖的对象.例如,一个 Twitter API 客户端可能需要通过 Retrofit 之类的网络库来构建.要使用这个库,你可能还需要添加 Gson 这样的解析库.另外,实

[Android]Android MVP&依赖注入&单元测试

以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5422443.html Android MVP&依赖注入&单元测试 注意:为了区分MVP中的View与Android中控件的View,以下MVP中的View使用Viewer来表示. 这里暂时先只讨论 Viewer 和 Presenter,Model暂时不去涉及. 1.1 MVP 基础框架 1.1.1 前提 首先需要解决以下问题: MVP中把Layout布局

依赖注入框架Autofac类型注册与简单使用

Autofac     Autofac是一套高效的依赖注入框架.     Autofac官方网站:http://autofac.org/     Autofac在Github上的开源项目:https://github.com/autofac/Autofac     Autofac安装:通过VS的Nuget可以很方便的获取. IoC/DI     关于IoC与DI的概念,网上有很多相关的博客,大家可以稍微了解一下,对比一下.     我个人的理解就是按照英文的中文翻译来理解的:     IoC:

依赖注入框架Autofac的简单使用

     Autofac是一款IOC框架,比较于其他的IOC框架,如Spring.NET,Unity,Castle等等所包含的,它很轻量级性能上也是很高的.于是,今天抽空研究了下它.下载地址:http://code.google.com/p/autofac/downloads/list http://www.cnblogs.com/liping13599168/archive/2011/07/16/2108209.html http://www.cnblogs.com/hkncd/archive

[Android]使用Dagger 2依赖注入 - DI介绍(翻译)

以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5092083.html 使用Dagger 2依赖注入 - DI介绍 原文:http://frogermcs.github.io/dependency-injection-with-dagger-2-introdution-to-di/ 不久之前,在克拉科夫的 Tech Space 的 Google I/O 扩展中,我 展示 了一些关于使用Dagger 2来进行依

[Android]使用Dagger 2依赖注入 - API(翻译)

以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5092525.html 使用Dagger 2依赖注入 - API 原文:http://frogermcs.github.io/dependency-injection-with-dagger-2-the-api/ 这章是展示使用Dagger 2在Android端实现依赖注入的系列中的一部分.今天我会探索Dagger 2的基础并且学习这个依赖注入框架的所有的API

[Android]使用Dagger 2依赖注入 - 图表创建的性能(翻译)

以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5098943.html 使用Dagger 2依赖注入 - 图表创建的性能 原文:http://frogermcs.github.io/dagger-graph-creation-performance/ #PerfMatters - 最近非常流行标签,尤其在Android世界中.不管怎样,apps只需要正常工作就可以的时代已经过去了.现在所有的一切都应该是令人愉

[Android]使用Dagger 2依赖注入 - 自定义Scope(翻译)

以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5095426.html 使用Dagger 2依赖注入 - 自定义Scope 原文:http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/ 这章是展示使用Dagger 2在Android端实现依赖注入的系列中的一部分.今天我会花点时间在自定义Scope(作用域)上面