在Kotlin中使用Dagger2最简单的入门例子


简介

    Dagger2是在编译期进行依赖注入的框架

依赖注入

    依赖注入(Dependency Injection,简称DI):它指不在类中实例化其他依赖的类,而是先把以来的类实例化了,然后以参数的形式传入构造函数中。它可以通过这种形式,减少类之间的依赖,从而降低耦合性。

比如我们想在类A中获得类B的实例,通常的做法是new一个类B的对象:


public class ClassA {
    public ClassA() {
        ClassB classB = new ClassB();
    }
}


这样ClassA和ClassB就是依赖的关系,比如这时由于需求变动,我需要更改ClassB的构造方法:

public class ClassB {
    private int num;
    public ClassB(int num) {
        this.num = num;
    }
}


那么我们就不得不去改ClassA,这就造成了耦合。
当然,你也会说,在ClassB里增加一个set方法或者空参构造不也行嘛,但是这只是一个简单的举例,实际需求前变万化,真正的解耦才是我们所不断追求的。


总之,我们的目标就是无论ClassB如何变动,我们都不用修改ClassA


常见的依赖注入方式

1.接口注入

interface ClassBInterface {
    void setB(ClassB b);
}

public class ClassA implements ClassBInterface {
    ClassB classB;

    @override
    void setB(ClassB b) {
        classB = b;
    }
}


2.构造方法注入

public class ClassA {
    ClassB classB;
    
    public void ClassA(ClassB b) {
        classB = b;
    }
}


3.set方法注入


public class ClassA {
    ClassB classB;
    
    public void setClassB(ClassB b) {
        classB = b;
    }
}


4.工厂模式注入(将需要依赖的类的实例化交给第三方类来实现注入)


public class Factory {
    public ClassB getClassB() {
        return new ClassB();
    }
}
public class ClassA {
    ClassB classB;
    
    public ClassA() {
        Factory factory = new Factory();
        ClassB classB = factory.getClassB();
    }
}


5.注解注入

本质上是依赖第三方类进行依赖注入的,但其通常可以通过映射关系自动生成第三方类,进行动态注入


public class ClassA {

    //注解注入需要依赖注入框架的支持,如Dagger2
    @Inject
    ClassB classB
        
}


Dagger2就是通过注解的方式进行依赖注入的




使用Dagger2

添加依赖


apply plugin: 'kotlin-kapt'
kapt {
    generateStubs = true
}

...

dependencies {

    ...

    //添加依赖
    implementation 'com.google.dagger:dagger:2.11'
    kapt 'com.google.dagger:dagger-compiler:2.11'
}


在kotlin中添加Dagger2的依赖和java中有所不同,重点在kapt上。
如果这里不使用kapt,则不会自动编译生成DaggerXXXComponent类
至于上方那些,就是kapt所需的配置


常用注解

@Inject 
        用于告诉Dagger2我们需要依赖哪个类的实例对象,如:


    @Inject
    lateinit var apiService:ApiService


注解注入所标识的成员,不允许使用private来修饰,而在kotlin中,声明的变量默认是私有的,这就需要我们单独处理一下,比如添加lateinit关键字或者添加@JvmField注解,如:

    @Inject
    @JvmField
    var apiService: ApiService? = null


通过以上的声明,Dagger2就知道,我们需要它帮我们注入一个ApiService类的apiService对象

@Module 
        标识着用于提供依赖的类,在其中使用 @Provides注解所标识的方法,就是提供依赖的方法,如:

@Module
class LoginModule {

    @Provides
    fun provideApiService(): ApiService = ApiService()
}


编程习惯上,@Module注解所标识的类名,使用Module结尾;@Provides注解所标识的方法名,使用provide开头


@Component 
        是 @Inject 和  @Module关联起来的桥梁,它需要是一个接口或抽象类,它将从 @Module中获取依赖并注入到 @Inject中,如:
@Component(modules = arrayOf(LoginModule::class))
interface LoginComponent {
    fun inject(activity: MainActivity)
}


编程习惯上,@Component  注解所标识的类名,使用Component  结尾; @Provides注解所标识的方法名,使用 provide开头

关联的@Module要 以集合的形式明确写出,可以关联多个 @ Module,如:


@Component(modules = arrayOf(LoginModule::class,RegisterModule::class))




最简单例子

了解了以上四个常用注解,我们就在Kotlin中写一个最简单的依赖注入:

我们所依赖的类ApiService


class ApiService {

    fun login() {
        Log.d("ApiService", "调用login")
    }
}


@Module 提供所需依赖


@Module
class LoginModule {

    @Provides
    fun provideApiService(): ApiService = ApiService()
}



@Component 建立@Inject 和 @Module 的关联


@Component(modules = arrayOf(LoginModule::class))
interface LoginComponent {
    fun inject(activity: MainActivity)
}


@Inject 声明所需依赖,并通过编译后生成DaggerXXXComponet类,完成依赖注入:


class MainActivity : AppCompatActivity() {

    //注入的成员不可以是私有的,而kotlin声明变量时,默认是私有的,所以我们需要特殊处理一下
//    @Inject
//    @JvmField
//    var apiService: ApiService? = null

    @Inject
    lateinit var apiService:ApiService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //按下Ctrol+F9 build项目,Dagger2会自动生成DaggerXXXComponet类
        DaggerLoginComponent.create().inject(this)
        apiService.login()
    }
}



参考:



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值