Android依赖注入: Dagger (Part 2)

Android依赖注入: Dagger (Part 2)

如果你读了依赖注入的第一篇文章,那么你可能正在寻找一些真实的代码.这里有一些不错的例子,coffee makers at Dagger page,还有一个特别好的model project by Jake Wharton适合有经验的用户.但是我们需要一些简单的,然而coffee并不是我们的主业务模型,所以这篇文章将会提供一个例子,来让我们了解简单的注入一些组件的基本知识.
源码可以在这里找到DaggerExample repository at Github.

在你的项目中加入Dagger

如果想使用Dagger,这里有两个库你需要加入.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.squareup.dagger:dagger:1.2.+'
    provided 'com.squareup.dagger:dagger-compiler:1.2.+'
}

第一个是Dagger库.第二个是dagger编译器.它将会创建一些需要的类以便可以进行依赖注入.这就是它为什么可以避免使用反射,使用预编译.因为我们只需要它来编译项目,不用在应用中使用,所以我们将它标记为provided,这样它就不会包含在我们的apk里了.

创建你第一个模型

模型将会便随着你使用dagger的每一天,所以你需要熟悉它们.模型是在需要注入的时候给其他对象提供实例的一些类.它们通过类注解@Module来定义.有一些其他的配置参数,一会我会讲到.

创建一个叫AppModule的类,它将会提供Application Context.通常是为了提供更方便的访问方式.在这之前,我创建了App类继承了Application,并加入到了Manifest中.

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

    private App app;

    public AppModule(App app) {
        this.app = app;
    }

    @Provides @Singleton public Context provideApplicationContext() {
        return app;
    }
}

译者注:建议配合上面提到的源码一起看,这样能比较完整的了解.源码并不多,只是为了表述Dagger的使用,很简单.

有什么新鲜的呢?

@Module:标志这个类是Dagger的模型.

injects:指定它要注入哪个类中的所有@Inject标记的变量(依赖).我们需要指出这些直接注入进对象图表(Graph)的类.一会会讲到这个.

Provides:标志这个方法是一个注入提供者.名字无所谓,它只依靠返回参数来表明它能提供什么类的实例.

Singleon:如果出现,这个方法将会总返回相同的实例,这比普通的单例模式要好得多.否则,每次这个类型进行注入的时候,将会创建一个新的实例.在这个例子中,因为我们并没有创建一个新的实例.只是返回了一个已经存在的,所以指不指定singleton无所谓,不过通过@Singleton指出它更好的解释了我们提供了什么–提供了唯一的Application.

为什么普通的单例是邪恶的

单例可能是我们项目中最危险的依赖.因为我们并没有创建一个实例,所以我们很难知道我们在哪里使用了它,这是”隐藏依赖”.另一方面,我们没有办法去模拟它们进行测试,或者将它替换成其他模块,所以我们的代码很难维护,测试和改进.注射单例,然而却不是这样,它既有单例的特点,我们又可以在任何时候创建任何一个新的实例,这样就很容易用另一块代码来模拟和替换,通过继承或者实现共同接口来实现.

我们将会在另一个包名为domain中创建一个新的模块.在不同的架构层次至少要有一个模块,这是非常有用的做法.这个模块将会提供分析统计管理器,将会在app启动时抛出一个事件(显示Toast).在真实项目中可以调用谷歌分析来进行统计.

@Module(
        complete = false,
        library = true
)
public class DomainModule {

    @Provides @Singleton public AnalyticsManager provideAnalyticsManager(Application app){
        return new AnalyticsManager(app);
    }

}

通过标记这个模块 complete = fale,表示这个模块中的一些依赖是其他模块提供的.在这个例子中就是Application,它是AppModule模块提供的.当我们请求AnalyticsManager来进行依赖注入的时候,dagger会使用这个provideAnalyticsManager方法,并且会发现这个方法需要另外一个Application依赖,然后它会去向对象图表(object graph)去请求.我们还需要指定这个模型为library,因为dagger编译会检查到AnalyticsManager既没有被自己使用也没有被它注射的类使用.它的行为就像是AppModule的一个库.

我们在AppModule中需要包含进这个模块.

@Module(
        injects = {
                App.class
        },
        includes = {
                DomainModule.class
        }
)
public class AppModule {
...
}

创建对象图表(Object Graph)

对象图表是所有依赖存在的地方.对象图表包含了创建的实例,并且可以注入到我们添加的那些对象中.

上一个例子中(AnalyticsManager)我们知道了通过典型的依赖注入,注入传入到构造器.但是有一些Android的类(Application, Activity)我们没办法控制他们的构造器,所以我们需要另一种方式来注入他们.

在App类中,包含了对象图表的创建和直接注入.对象图表在Application类中被创建,并且为了获得它的依赖而进行注入.

public class App extends Application {

    private ObjectGraph objectGraph;
    @Inject AnalyticsManager analyticsManager;

    @Override public void onCreate() {
        super.onCreate();
        objectGraph = ObjectGraph.create(getModules().toArray());
        objectGraph.inject(this);
        analyticsManager.registerAppEnter();
    }

    private List<Object> getModules() {
        return Arrays.<Object>asList(new AppModule(this));
    }
}

我们通过@Inject注解来进行注入.注意这个域(属性)必须是public或者是default的,这样dagger才可以给它们赋值.我们还为这些模块(虽然例子中只有一个,DomainModule是被包含进AppModule的)创建了数组,通过数组创建了对象图表.之后,我们立即手动的进行了注入.在调用objectGraph.inject(this)之后,依赖就被注入了,我们就可以调用AnalyticsManager的方法了!

结论

现在你知道Dagger的基本使用了.对象图表和模型是dagger最重要的组件,我们必须使用好它们,这样才能有效率的使用dagger.还有一些类似于懒注入(lazy injections)和提供注入(provider injections),在Dagger site这里有解释.但我建议当你还没有流畅的使用dagger之前不要去钻研这些.

不要忘了在Github上的例子源码.

接下来,可能是最后一篇关于Dagger的文章将集中讲解指定域的对象图表.就是有生命期的对象图表,一般用于在Activity中使用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值