您的位置:首页 > 移动开发 > Android开发

Android 依赖注入:Dagger 实例讲解(Demo下载)

2015-04-16 18:12 441 查看


Android 依赖注入:Dagger 实例讲解(Demo下载)

分类: android2014-01-24
23:50 6451人阅读 评论(3) 收藏 举报

androidDaggerDependency

(Dagger--A fast dependency injector for Android and Java 实例讲解)

IDE: AndroidStudio 4.2

Dagger 是一种android平台的依赖注入框架,是有一家专注于移动支付的公司,Square公司推出的库,这家公司也推出了

其他在Android开发中常用库:otto,okhttp,retrofit等等,这些在接下的博文中会一一介绍。

对Dagge的介绍,除了官方文档的介绍外,接下来的这些分析,本人觉得是比较不错的,也许在不熟悉Dagger的情况下看这

写内容,你会觉得无厘头,不知道讲什么。根据本人经验,建议先了解Dagger的使用再来看这个会对了解Dagger有比较好的效果。

如果你不喜欢看英文官方文档介绍,请参考:http://fanxu.me/post/2013-07-18

Dagger的简介,请阅读:http://www.infoq.com/cn/news/2012/10/dagger

接下来就进入正题,进行实例讲解,与官方例子一样,我这里也用煮咖啡的例子来说明,只不过官方的例子是用在Java上,这里

的例子使用Android开发来进行,并且对其也进行了改进。

首先我先说明一下这个过程,既然是煮咖啡,就要由一个加热器(Heater),加热之后要有一个倒(Pump)的过程,倒好之后才能供给人

们喝(Drink)。就这么一个简单的逻辑,你也许会和我开始一样,觉得这有什么难的,很少的代码就能搞定。是的,我们就要用这么一

个简单的事件,来看看用Dagger是怎么实现的。

首先,我们来设计Heater、Pump、Drink这三个接口,如下:

[java] view
plaincopyprint?





package com.example.app.dagger;

/**

* Created by zjb on 14-1-22.

*/

interface Heater {

void on(); //加热器打开

void off();//加热器关闭

boolean isHot();//加热是否完毕

}

[java] view
plaincopyprint?





package com.example.app.dagger;

/**

* Created by zjb on 14-1-22.

*/

interface Pump {

void pump(); //倒咖啡

boolean isPumped();//是否倒好

}

[java] view
plaincopyprint?





package com.example.app.dagger;

/**

* Created by zjb on 14-1-22.

*/

interface Drink {

void drink(); //喝咖啡

}

Ok,接口已经设计完毕,是否合理暂且不细究,接下来我们分别实现这三个接口(有用到AndroidAnnotations框架(请看上篇博文)):

[java] view
plaincopyprint?





package com.example.app.dagger;

import android.content.Context;

import android.widget.Toast;

import org.androidannotations.annotations.EBean;

import org.androidannotations.annotations.RootContext;

import org.androidannotations.annotations.UiThread;

/**

* Created by zjb on 14-1-22.

*/

@EBean

class ElectricHeater implements Heater {

boolean heating = false;

@RootContext

Context context;

@Override

public void on() {

heating = true;

System.out.println("-----Heating-----");

reportHeating();

}

@UiThread

void reportHeating(){

Toast.makeText(context,"Electric heater heating.....",Toast.LENGTH_LONG).show();

}

@Override

public void off() {

heating = false;

}

@Override

public boolean isHot() {

return heating;

}

}

ElectricHeater是对Heater接口的实现类,@EBean,@RootContext,@UiThread是AndroidAnnotations框架中的注解。

使用@EBean注解会在编译过程中产生一个ElectricHeater子类ElectricHeater_.class, 接下来会用到。

Pump接口实现:

[java] view
plaincopyprint?





package com.example.app.dagger;

import javax.inject.Inject;

/**

* Created by zjb on 14-1-22.

*/

class Thermosiphon implements Pump {

private final Heater heater;

boolean pumped = false;

@Inject

Thermosiphon(Heater heater) {

this.heater = heater;

}

@Override

public void pump() {

if (heater.isHot()) {

System.out.println("-----Pumping-----");

pumped = true;

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

@Override

public boolean isPumped() {

return pumped;

}

}

[java] view
plaincopyprint?





package com.example.app.dagger;

import javax.inject.Inject;

/**

* Created by zjb on 14-1-22.

*/

class PeopleDrink implements Drink {

private Pump pump;

@Inject

PeopleDrink(Pump pump) {

this.pump = pump;

}

@Override

public void drink(){

if(pump.isPumped()){

System.out.println("-----Drinking-----");

}

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

三个接口已经实现完毕,对比三个实现类,有没有发现什么共同点. 是的,你会发现,三个类中都有使用@Inject来注解

他们的构造函数,这是因为Dagger要用@Inject来注解一个类的实例构造函数,当请求一个新实例的时侯,Dagger就会获取这个

参数值并调用这个构造函数。也许你不明白,没关系,继续往下看,会给出详细解释。

Dagger不仅能向上述代码那样注解构造函数,也能直接注解fields(Dagger can inject fields directly),看这个类:

[java] view
plaincopyprint?





package com.example.app.dagger;

import javax.inject.Inject;

import dagger.Lazy;

/**

* Created by zjb on 14-1-22.

*/

class CoffeeMaker {

@Inject

Lazy<Heater> heater;

@Inject

Pump pump;

@Inject

Drink drink;

public void brew() {

heater.get().on();

pump.pump();

System.out.println("-----Pumped-----");

heater.get().off();

drink.drink();

}

}

将Heater、Pump及Drink注入到类CoffeeMaker中,就可以直接使用并调用其方法。值得注意的是,在注解的时候Dagger

就会通过@Module中的@Provides方法调用构造函数来获得实例对象(下面马上介绍)。如果你@Inject fields却没有@Inject

构造函数,Dagger就会使用一个存在的无参构造函数,若没有@Inject构造函数,就会出错。继续看@Module

[java] view
plaincopyprint?





package com.example.app.dagger;

import android.content.Context;

import javax.inject.Singleton;

import dagger.Module;

import dagger.Provides;

/**

* Created by zjb on 14-1-22.

*/

@Module(injects={CoffeeActivity_.class},library = true,complete = false)

/*@Module(injects = {CoffeeActivity_.class},includes = {PumpModule.class,DrinkModule.class},library = true,complete = false)*/

class DripCoffeeModule {

private final Context context;

public DripCoffeeModule(Context context) {

this.context = context.getApplicationContext();

}

@Provides

@Singleton

Context appliactionContext() {

return context;

}

@Provides

@Singleton

Heater provideHeater(){

return ElectricHeater_.getInstance_(appliactionContext());

}

@Provides

@Singleton

Drink provideDrink(PeopleDrink drink){

return drink;

}

@Provides

@Singleton

Pump providePump(Thermosiphon pump){

return pump;

}

}

上面就是使用@Module注解的类,Dagger要求所有的@Provides必须属于一个Module.他们仅仅是一个使用@Module注解的类。

解释一下前面一句话:如果说@Inject实现了注入,那么@Provides就是实现依赖关系。@Provides方法方法的返回类型就定义了它

所满足的依赖。你也许注意到了我注释掉的@Module,这是什么意思呢?是这样的,假如我这里将providesDrink方法删除,我可以

另建一个DrinkModule.java文件,由于所有的@Provides必须属于一个Module,所以必须将DrinkModule类includes进来:

[java] view
plaincopyprint?





package com.example.app.dagger;

import dagger.Module;

/**

* Created by zjb on 14-1-22.

*/

@Module(library = true,complete = false)

public class DrinkModule {

@Provides

@Singleton

Drink provideDrink(PeopleDrink drink){

return drink;

}

}

(@Module后的library和complete是什么意思这里先不说)

至此,Dagger中的三个重要annotation已经全部涉及到了,那么它是如何管理这些依赖关系的呢?继续往下看:

[java] view
plaincopyprint?





package com.example.app.dagger;

import android.app.Application;

import org.androidannotations.annotations.EApplication;

import dagger.ObjectGraph;

/**

* Created by zjb on 14-1-22.

*/

@EApplication

public class CoffeeApplication extends Application {

private ObjectGraph objectGraph;

@Override

public void onCreate() {

super.onCreate();

objectGraph = ObjectGraph.create(new DripCoffeeModule(this));

}

public ObjectGraph getObjectGraph() {

return objectGraph;

}

}

上边提到,Dagger是通过什么管理或者组织依赖关系的呢,就是通过ObjectGraph(对象图表)。

最后的主程序:在节面中就一个按钮来触发整个过程

[java] view
plaincopyprint?





package com.example.app.dagger;

import android.app.Activity;

import android.widget.Toast;

import com.example.app.R;

import org.androidannotations.annotations.AfterInject;

import org.androidannotations.annotations.App;

import org.androidannotations.annotations.Background;

import org.androidannotations.annotations.Click;

import org.androidannotations.annotations.EActivity;

import org.androidannotations.annotations.UiThread;

import javax.inject.Inject;

import dagger.ObjectGraph;

/**

* Created by zjb on 14-1-22.

*/

@EActivity(R.layout.coffee)

public class CoffeeActivity extends Activity {

@App

CoffeeApplication coffeeApplication;

@Inject

CoffeeMaker maker;

@AfterInject

void daggerInject(){

ObjectGraph objectGraph = coffeeApplication.getObjectGraph();

objectGraph.inject(this);

}

@Click(R.id.coffeeClick)

@Background

void coffeeClicked(){

maker.brew();

coffeeBrew();

}

@UiThread

void coffeeBrew(){

Toast.makeText(this,"Coffee has been pumped...",Toast.LENGTH_LONG).show();

}

}

程序运行的结果:

[java] view
plaincopyprint?





com.example.app I/System.out﹕ -----Heating-----

com.example.app I/System.out﹕ -----Pumping-----

com.example.app I/System.out﹕ -----Pumped-----

com.example.app I/System.out﹕ -----Drinking-----

使用Dagger,我们能够很好的实现依赖关系,也能更清楚的看到我们的代码在做些事情,能够清晰地显示出各部分的

逻辑关系,通过下面这张图,我们能够很清楚的看到它的每一步操作:



好了,Dagger呢就介绍到这里,源码这次就先不上传了,等到介绍完Otto之后,我会抽空上传到资源,供大家下载学习。

内容细节说的不全请见谅、指教。如果你对使用dagger有兴趣也欢迎一起讨论、学习。这是春节前最后一篇文章了,祝大家

抢到一张好票,马上有钱、有对象!

注:文章原创 转载请注明出处:CSDN 菜鸟的成长史

附:

Demo 下载

Jake Warhton的Dagger ppt 下载资源
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: