资讯专栏INFORMATION COLUMN

Dagger2 —— 匪夷所思,结果那么爱你

Jokcy / 1292人阅读

摘要:官网组成以下称为主要由两个部分组成和。注解表示这个类是个,是一个源。控制变量生命周期,实质就是控制它存在的作用域,服务端典型的作用域如单例,,,等等,它们的变量分别存在于不同的生命周期。那么我们采取的方案有两种,双表,或者双库。

开天辟地

今天我们来讲讲一个有一点点冷门的库Dagger吧。我做一个不负责任的猜测:做客户端的同学可能比较少听到一些名
词,比如面向切面编程控制反转依赖注入,相信玩过Spring的同学肯定知道这些一开始让人头大后来却很好玩的玩意儿。

今天我们来介绍这款依赖注入器 —— Dagger2,源自Square的Dagger,由Google开发,基于apt生成静态编译时的依赖注入工具,比动态注入的方式更加高性能,但是需要更多的约定。

官网:https://google.github.io/dagger/

组成

Dagger2(以下称为Dagger) 主要由两个部分组成:ComponentModule。分别作为注入器和注入源存在于整个依赖图中,然后有了工具,那么只用在我们需要注入的地方加上@Inject注解即可,它是属于JSR-330的一部分,我们这里就直接引入一个最简单的Demo。

Module
@Module
public class AppModule {
    Context mApplicationContext;

    public AppModule(Context context) {
        this.mApplicationContext = context;
    }

    @Provides
    public Context provideContext(){
        return mApplicationContext;
    }

    @Provides
    public Service provideService(Context context) {
        return new Service(context, null);
    }
}

这是世界的起源。

@Module注解表示这个类是个Module,是一个“源”。

@Provides注解告诉Dagger我们想要构造对象并提供这些依赖。

Component
@Component(modules=AppModule.class)
public interface AppComponent {
    void inject(App app);

    Context context();
    Service service();
}

Component是一个接口,具体的实现由Dagger经过apt工具为你生成(是不是有了apt就特别爽),我们给AppComponent这枚“针”指定了药剂——AppModule,告诉它注入的时候,从AppModule里面拿到我们要的变量实例,只要给Component声明一个无返回值,带被注入类型形参的方法,Dagger 就会为这个类生成一个MemberInjector对象,用来给被注入类注入对象。

被注入对象
public class App extends Application {

    @Inject Service mService;
    
    private AppComponent mAppComponent;

    /**
     * 应用程序初始化
     */
    @Override
    public void onCreate() {
        super.onCreate();
        mAppComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this))
                .build();

        mAppComponent.inject(this);

    }
    
    public AppComponent getAppComponent() {
        return mAppComponent;
    }
}

这里的DaggerAppComponentDagger生成的,它的实现类会在所有Component接口类之前增加一个Dagger前缀,我们只用传入它所需要的依赖即可,Component显然是依赖Module的,所以需要在这里传入AppModule,现在,只要用Context的地方,我们都可以拿到这个AppComponent实例,只要有这个实例,我们可以在任意地方注入被管理的类。

作用域

我们说依赖注入的时候,作用域(Scope)是经常会出现在我们眼里的词汇。控制变量生命周期,实质就是控制它存在的作用域,服务端典型的作用域如单例(Singleton)RequestSession,等等,它们的变量分别存在于不同的生命周期。

我们默认存在的是Singleton,也就是@Singleton注解。由它标注的Provider生成的对象会被缓存起来,用SingleCheck或者DoubleCheck进行包装。我们Provider指定的作用域需要和Component的作用域一致。

比如Component这样定义:

@Singleton
@Component(modules=AppModule.class)
public interface AppComponent {
    void inject(App app);

    Service service();
}

Module就是这个样子

@Module
public class AppModule {
    Context mApplicationContext;

    public AppModule(Context context) {
        this.mApplicationContext = context;
    }

    @Singleton
    @Provides
    public Context provideService(){
        return new Service();
    }

}
限定符

Dagger还支持使用限定符(Qualifier)来指定注入的对象,比如内置的@Named限定符,我们在需要特定限定名字的变量的时候,可以在@Inject上,指定@Named限定符,获取指定对象。

//Module
@Providers
@Named("cache")
public Service provideService();

// Injection
@Inject
@Named("cache")
Service mService;

这样就给这个mService注入了名字为"cache"的实例了。

一个简单场景的应用

当我们谈论依赖注入的时候,我们在谈论什么?
其实我们是在讨论 作用域

这是什么意思呢,我相信每一个程序员去实现一个单例是一件非常简单的事情,makeInstancegetInstance嘛。但是,你们想过维护“双例”吗?我之前碰到了一个场景如下:

用户(User) 需要一张tag表,会增删查改,并和用户相关联。

问题(Question) 也需要一张tag表,也会增删查改,和问题关联。

这两张表的实体模型一模一样。

那么我们采取的方案有两种,双表,或者双库。双表的话,对ORM很不友好,因为ORM是根据类来确定表的,我们为了代码简洁优雅,不可能创建两个一模一样的类,不然取名都变成一件困难的事。这里,一个优势是,我使用的ORM
库首先是维护一个单例,单例进行CRUD操作,且一个单例和一个数据库相关。于是我使用Qualifer的特性,生成了两个实例(也就是对应了两个数据库),分别注入到不同的业务模型中去,他们就可以使用同一个类,而且对tag的修改完全没有影响。
这件事要是我们自己去做的话,可能要写很多肮脏不堪的代码,但是Dagger只用2个注解就把我的需求解决了。

总结

好了,本文简单的阐述了Dagger入门使用,总结起来,我们只要约定好ComponenetModule,搭配Inject使用,即可实现一个静态的依赖注入流程。下一次我们详细介绍Dagger生成的代码结构。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/13335.html

相关文章

  • 神兵利器Dagger2

    摘要:方案我们手动以构造函数的方式注入依赖,将和作为参数传入而不是在的构造函数中去显示的创建。同样我们需要在类的成员变量上加上表示自己需要为自己提供依赖类的构造函数上的也需要去掉,应为现在不需要通过构造函数上的来提供依赖了。 Dagger-匕首,鼎鼎大名的Square公司旗下又一把利刃(没错!还有一把黄油刀,唤作ButterKnife);故此给本篇取名神兵利器Dagger2。 Dagger2...

    summerpxy 评论0 收藏0
  • 神兵利器Dagger2

    摘要:方案我们手动以构造函数的方式注入依赖,将和作为参数传入而不是在的构造函数中去显示的创建。同样我们需要在类的成员变量上加上表示自己需要为自己提供依赖类的构造函数上的也需要去掉,应为现在不需要通过构造函数上的来提供依赖了。 Dagger-匕首,鼎鼎大名的Square公司旗下又一把利刃(没错!还有一把黄油刀,唤作ButterKnife);故此给本篇取名神兵利器Dagger2。 Dagger2...

    _DangJin 评论0 收藏0
  • Dagger2入门教程

    摘要:由此来看,解除了和的依赖,而和产生了依赖容器。依赖注入的好处解耦,解除对象之间的依赖关系。在出来之前,也存在一些依赖注入框架如。 1、Android依赖注入简介 1.1 依赖注入(ICO:Inversion of Control) (1)依赖注入概念依赖注入将来单说就是非自己主动初始化依赖,而通过外部来传入依赖的方式,我们就称为依赖注。举例来说:如下面的代码所示,A是依赖注入的例子,B...

    Juven 评论0 收藏0
  • Dagger2-终于学会了,还好没放弃(1)

    摘要:箱子里装有苹果。那怎么生成一个对象呢,很容易想到在构造函数前加一个,如但是既然能让它自动生成,我们当然不需要自己动手,只需要做某种标记,比如可以直接加上注解。 MVP + RxJava + Retrofit + Dagger2 如今已经成了Android开发的主流框架,为了不落伍,我也开始了这个组合框架的学习,力求摆脱之前的那种简单粗暴的分包模式。于是也开始了 Dagger2 的学习之...

    2501207950 评论0 收藏0
  • Dagger2 在 Android 中实现依赖注入

    摘要:尤其反射消耗比较大所以为了满足移动开发节约资源的需要,没有使用反射实现依赖注入。厉害的地方就在于这个库完全不用反射,而是用在编译期生成代码的方式实现的依赖注入。这里表明一个依赖关系这个依赖于悟空,并准备注入悟空对象。 依赖注入这个模式(模式已经用烂了,这里再烂一次)是用来给应用的各部分解耦的。使应用开发更加可扩展,更容易维护。通过本文你会学到如何使用Dagger2来处理依赖。 简介 如...

    fnngj 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<