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

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

软件应该符合 SOLID 原则。

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

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

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

概述

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


  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 处理将会很糟糕。

作者:Roberto Orgiu

来源:51CTO

时间: 2024-09-17 04:04:26

安卓平台上的依赖注入(一)的相关文章

ios-使用Unity 3D在IOS及安卓平台上实现消息推送

问题描述 使用Unity 3D在IOS及安卓平台上实现消息推送 要求如标题,使用Unity 3D在不打开应用程序的情况下,可以实现消息推送. 请告知实现逻辑和关键的代码,如果有调用API接口,请描述API接口的名称及调用参数. PS.不是程序员,代人提问,描述不清楚的地方请提出勿喷,我会询问后补充. PSS.公司急求,解决问题实现功能的可以提供赏金.可以网上搜索悬赏任务(详细就不说了省的被删),也可以通过站内消息沟通联系.

android-小波变换实现语音去噪在安卓平台上怎么实现?求大神指点~~

问题描述 小波变换实现语音去噪在安卓平台上怎么实现?求大神指点~~ 本人要在Android平台上实现小波变换的语音去噪方法,请问怎么实现?求大神指点~~ 解决方案 可以利用speex进行降噪处理

你的手机防护罩 安卓平台上最好的杀毒应用

[TechWeb报道]尽管安卓系统本身有一定的防护能力,但大部分人还是觉得不放心,害怕各种病毒木马给自己造成损失.外媒Androidauthority就推荐了一些最棒的安卓杀毒应用供我们选择.如果你想大胆用安卓手机网购和转账,那么下列应用会大大提高你的安全系数.Antivirus & Mobile Security (免费)TrustGo公司的这款应用也值得一试.它不仅有基本的杀毒功能,还提供网页防护,数据备份等实用大招.但是你在卸载它时会很头痛,虽然可以做到但相当麻烦.AVG Antiviru

天天睡好觉 安卓平台上最棒的那些安眠应用

[TechWeb报道]失眠虽然可怕,但它并不是不治之症.有些长期失眠的人都要抓狂了,但对大部分人来说 这不是个大问题.外媒AndroidCentral就向我们推荐了一些非常给力的安眠应用,如果你已经尝试了以下的这些应用但还是休息不好的话,我们建议你还是去咨询医生.如果你只是需要一点帮助或鼓励,那么这些应用会很适合你.Do Not Disturb我们先从关掉声音开始.你一 整天都受手机上的各种通知奴役,现在是时候闭上眼睛休息了.现在许多手机都能设置一段禁音时间,让手机铃声和通知不再吵到你.如果你的

10分钟理解依赖注入

看到网络上很多"依赖注入"解释的话题,这篇博客呢也只是我自己的观点,如果你有不同的观点请拍砖,不用客气. 业务场景 小明要去旅游,但是还未确定以什么方式出游,有可能是徒步旅行,也有可能是自驾游. 代码演示 根据步行和驾车的速度来考虑距离旅游目的地的路程,所以这里定义了两个属性$speed和$distance.所有有了如下代码: interface travelInterface{ public function __construct($speed, $distance); publi

Go 语言将登陆安卓平台

根据谷歌Go语言开发团队成员David Crawshaw的透露,Go语言即将登陆安卓平台.对 那些讨厌安卓平台上只有Java的人来说,虽然等来的不是Dart语言或Groovy语言,这仍然是一个让人欢欣鼓舞的消息.并不是将Go语言实现成完全 的可替换Java.计划中Go语言在安卓平台上的封装并没有全面涉及Android SDK,而是基于NDK.对于Go语言来说--Crawshaw评论道--SDK实在是太庞大了:让Go语言在安卓平台上和Java等效--这是无法完成 的任务. 安卓平台用Java写出,

龙年起航 2012年安卓平台新作手游抢先玩

2012年安卓平台新作手游推荐(一)时光转瞬即逝,如今我们已经告别了2011年,迎来了2012年.在过去的一年中,手机游戏市场又为我们呈现了一番你争我夺的情景.这其中不仅仅是手机游戏厂商之间的角逐,也不止是个人开发者之间的竞争,更多的是各大系统平台之间的对抗.在应用领域,苹果的 AppStore可谓是一家独大,Android Market也紧随其后.其实对于安卓平台不利的一项因素便是没有自己的特色软件或游戏诞生.我们能看到的更多是某某应用移植自iOS.无论如 何, Android平台仍旧拥有庞大

Unity(六):使用场景Ⅲ:用于依赖注入(上)

有关依赖注入 什么是依赖注入,我想这个问题我在这里说就不大合适了,所以还是推荐一下大师的文章.之前的文章也提到过,"Martin Fowler的Inversion of Control Containers and the Dependency Injection pattern 是不得不推荐的,当然,如果读起来比较费劲的话,吕震宇的你真的了解Ioc与AOP吗?系列也是不错的参考". 这里要多说一句的是,依赖注入(Dependency Injection)和控制反转(Inversion

基于.NET平台的分层架构实战(六)—依赖注入机制及IoC的设计

我们设计的分层架构,层与层之间应该是松散耦合的.因为是单向单一调用, 所以,这里的"松散耦合"实际是指上层类不能具体依赖于下层类, 而应该依赖于下层提供的一个接口.这样,上层类不能直接实例化下层中的类, 而只持有接口,至于接口所指变量最终究竟是哪一个类,则由依赖注入机制决定 . 之所以这样做,是为了实现层与层之间的"可替换"式设计 ,例如,现在需要换一种方式实现数据访问层,只要这个实现遵循了前面定义的 数据访问层接口,业务逻辑层和表示层不需要做任何改动,只需要改一下