安卓平台上的依赖注入(一)

移动开发 Android
要注入依赖,首先需要告诉框架我们能提供什么(比如说上下文)以及特定的对象应该怎样创建。为了完成注入,我们用 @Module 注释对一个特殊的类进行了注解(这样 Dagger 就能识别它了),寻找 @Provide 注解的方法,生成图表,能够返回我们所请求的对象。

刚开始学习软件工程的时候,我们经常会碰到像这样的事情:

软件应该符合 SOLID 原则。

但这句话实际是什么意思?让我们看看 SOLID 中每个字母在架构里所代表的重要含义,例如:

  • S - 单职责原则
  • O - 开闭原则
  • L - Liskov 替换原则
  • I - 接口分离原则
  • D - 依赖反转原则 这也是依赖注入(dependency injection)的核心概念。

简单来说,我们需要提供一个类,这个类有它所需要的所有对象,以便实现其功能。

[[180033]]

概述

依赖注入听起来像是描述非常复杂的东西的一个术语,但实际上它很简单,看下面这个例子你就明白了:

  1. class NoDependencyInjection { 
  2.   private Dependency d; 
  3.   public NoDependencyInjection() { 
  4.     d = new Dependency(); 
  5.   } 
  6. class DependencyInjection { 
  7.   private Dependency d; 
  8.   public DependencyInjection(Dependency d) { 
  9.     this.d = d; 
  10.   } 

正如我们所见,***种情况是我们在构造器里创建了依赖对象,但在第二种情况下,它作为参数被传递给构造器,这就是我们所说的依赖注入(dependency injection)。这样做是为了让我们所写的类不依靠特定依赖关系的实现,却能直接使用它。

参数传递的目标是构造器,我们就称之为构造器依赖注入;或者是某个方法,就称之为方法依赖注入:

  1. class Example { 
  2.   private ConstructorDependency cd; 
  3.   private MethodDependency md; 
  4.   Example(ConstructorDependency cd) { 
  5.     this.cd = cd; //Constructor Dependency Injection 
  6.   } 
  7.   public setMethodDependency(MethodDependency md) { 
  8.     this.md = md; //Method Dependency Injection 
  9.   } 

要是你想总体深入地了解依赖注入,可以看看由 Dan Lew 发表的精彩的演讲,事实上是这个演讲启迪了这篇概述。

在 Android 平台,当需要框架来处理依赖注入这个特殊的问题时,我们有不同的选择,其中最有名的框架就是 Dagger 2。它最开始是由 Square 公司(LCTT 译注:Square 是美国一家移动支付公司)的一些很棒的开发者开发出来的,然后慢慢发展成由 Google 自己开发。首先开发出来的是 Dagger 1,然后 Big G 接手这个项目发布了第二个版本,做了很多改动,比如以注解(annotation)为基础,在编译的时候完成其任务。

导入框架

安装 Dagger 并不难,但需要导入 android-apt 插件,通过向项目的根目录下的 build.gradle 文件中添加它的依赖关系:

  1. buildscript{ 
  2.   ... 
  3.   dependencies{ 
  4.     ... 
  5.     classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8’ 
  6.   } 

然后,我们需要将 android-apt 插件应用到项目 build.gradle 文件,放在文件顶部 Android application 那一句的下一行:

  1. apply plugin: ‘com.neenbedankt.android-apt’ 

这个时候,我们只用添加依赖关系,然后就能使用库及其注解(annotation)了:

  1. dependencies{ 
  2.     ... 
  3.     compile ‘com.google.dagger:dagger:2.6’  
  4.     apt ‘com.google.dagger:dagger-compiler:2.6’ 
  5.     provided ‘javax.annotation:jsr250-api:1.0’ 

需要加上***一个依赖关系是因为 @Generated 注解在 Android 里还不可用,但它是原生的 Java 注解。

Dagger 模块

要注入依赖,首先需要告诉框架我们能提供什么(比如说上下文)以及特定的对象应该怎样创建。为了完成注入,我们用 @Module 注释对一个特殊的类进行了注解(这样 Dagger 就能识别它了),寻找 @Provide 注解的方法,生成图表,能够返回我们所请求的对象。

看下面的例子,这里我们创建了一个模块,它会返回给我们 ConnectivityManager,所以我们要把 Context 对象传给这个模块的构造器。

  1. @Module 
  2. public class ApplicationModule { 
  3.   private final Context context; 
  4.   public ApplicationModule(Context context) { 
  5.     this.context = context; 
  6.   } 
  7.   @Provides @Singleton 
  8.   public Context providesContext() { 
  9.     return context; 
  10.   } 
  11.   @Provides @Singleton 
  12.   public ConnectivityManager providesConnectivityManager(Context context) { 
  13.     return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 
  14.   } 

Dagger 中十分有意思的一点是简单地注解一个方法来提供一个单例(Singleton),就能处理所有从 Java 中继承过来的问题。

组件

当我们有一个模块的时候,我们需要告诉 Dagger 想把依赖注入到哪里:我们在一个组件(Component)里完成依赖注入,这是一个我们特别创建的特殊注解接口。我们在这个接口里创造不同的方法,而接口的参数是我们想注入依赖关系的类。

下面给出一个例子并告诉 Dagger 我们想要 MainActivity 类能够接受 ConnectivityManager(或者在图表里的其它依赖对象)。我们只要做类似以下的事:

  1. @Singleton 
  2. @Component(modules = {ApplicationModule.class}) 
  3. public interface ApplicationComponent { 
  4.   void inject(MainActivity activity); 

正如我们所见,@Component 注解有几个参数,一个是所支持的模块的数组,代表它能提供的依赖。这里既可以是 Context 也可以是 ConnectivityManager,因为它们在 ApplicationModule 类中有声明。

用法

这时,我们要做的是尽快创建组件(比如在应用的 onCreate 阶段)并返回它,那么类就能用它来注入依赖了:

为了让框架自动生成 DaggerApplicationComponent,我们需要构建项目以便 Dagger 能够扫描我们的代码,并生成我们需要的部分。

在 MainActivity 里,我们要做的两件事是用 @Inject 注解符对想要注入的属性进行注解,调用我们在 ApplicationComponent 接口中声明的方法(请注意后面一部分会因我们使用的注入类型的不同而变化,但这里简单起见我们不去管它),然后依赖就被注入了,我们就能自由使用他们:

  1. public class MainActivity extends AppCompatActivity { 
  2.   @Inject 
  3.   ConnectivityManager manager; 
  4.   @Override 
  5.   protected void onCreate(Bundle savedInstanceState) { 
  6.     ... 
  7.     ((App) getApplication()).getComponent().inject(this); 
  8.   } 

总结

当然了,我们可以手动注入依赖,管理所有不同的对象,但 Dagger 消除了很多比如模板这样的“噪声”,给我们提供有用的附加品(比如 Singleton),而仅用 Java 处理将会很糟糕。

责任编辑:庞桂玉 来源: Linux中国
相关推荐

2012-08-22 11:12:11

Ubuntu

2018-11-01 10:45:24

2022-01-21 10:35:03

Windows 11微软安卓

2013-06-24 17:20:29

x86平台优化安卓x86

2022-12-29 08:54:53

依赖注入JavaScript

2013-12-12 16:23:53

安卓进化AndroidGoogle

2023-06-27 08:58:13

quarkusBean

2012-06-12 09:43:34

微软Linux服务

2009-01-16 09:10:39

JavaCRM系统企业应用

2015-09-02 11:22:36

JavaScript实现思路

2011-05-31 10:00:21

Android Spring 依赖注入

2015-10-09 10:32:21

代码依赖注入强心剂

2023-07-11 09:14:12

Beanquarkus

2010-12-22 21:52:12

rkhunter

2024-05-27 00:13:27

Go语言框架

2019-11-26 14:52:40

Linux工具写作者

2017-02-23 13:51:05

2015-07-13 09:21:27

2021-01-22 06:35:44

IoCxml驱动技术

2017-08-16 16:00:05

PHPcontainer依赖注入
点赞
收藏

51CTO技术栈公众号