轻量级依赖注入框架koin简析

说到依赖注入框架,Android开发者一定最先想到dagger2,但是dagger2是Java的产物,Android的开发语言已经向kotlin切换,虽然Java与kotlin是完全兼容的,但是基于kotlin语言的一些优异特性一定能诞生出许多更适用于kotlin语言环境的新的框架来,koin正是其中一个。

  • 什么是Koin?

Koin是用于Kotlin开发人员(实际也可用于Java开发中)的实用轻量级依赖注入框架。用纯Kotlin编写,仅使用方法来解决问题:无代理,无代码生成,无反射。Koin是一个DSL,一个轻量级容器和一个实用的API。
github地址:https://github.com/InsertKoinIO/koin

  • 如何在项目中使用:

将koin-core依赖项添加到Gradle项目

// Add Jcenter to your repositories if needed
repositories {
    jcenter()
}
dependencies {
    // Koin for Android
    implementation 'org.koin:koin-android:1.0.2'
}

得益于Kotlin语言的强大功能,koin提供了一个DSL(domain-specific language)来帮助我们描述应用,而不是添加注解或为其生成代码。这些注解最终还是需要代码来分析,从而进行(动态)代理或者生成代码。而使用Kotlin DSL,我们可以使用智能功能API来实现相同的目标:进行依赖注入。
Koin的使用非常简单,下面我们通过一个实例来展示如何快速注入:
首先我们创建一个接口

interface LoginService {
    fun login()
    fun unLogin()
}

接着我们创建接口的实现

class LoginServiceImpl:LoginService {
    override fun login() {
        println("login")
    }

    override fun unLogin() {
        println("unLogin")
    }
}

然后我们声明这个组件

class KoinApplication: Application() {
    private val loginModule = module {
        single { LoginServiceImpl() }//以单例模式声明将这个组件定义绑定到LoginService
    }

    override fun onCreate() {
        super.onCreate()
        startKoin(this, arrayListOf(loginModule))//将声明的组件注册到koin
    }
}

接下来我们就可以使用koin来为我们注入组件了
只要在要使用的Activity,Fragment等应用组件中添加如下注入声明

private val loginService: LoginService by inject()

koin会通过懒加载的方式,在使用该实例时为我们注入LoginServiceImpl的实例。
当然也可以不通过懒加载,直接获得实例

private val loginService: LoginService = get()

当然,组件定义也可以是带参数的

 private val loginModule = module {
        single { (code: String) ->LoginServiceImpl(code) }//声明将这个组件定义绑定到LoginService
    }

在注入时,传入注入所需参数即可

private val loginService: LoginService by inject { parametersOf("123") }

全部调用代码:

class MainActivity : AppCompatActivity() {
    private val loginService: LoginService by inject { parametersOf("123") }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        loginService.login()
        loginService.unLogin()
    }
}

熟悉依赖注入框架的朋友可能都知道,在Java中,依赖注入通常使用注解,依靠动态代理,或者apt,或者反射来实现注入功能,那么koin不依靠上面的技术是如何做到这一切的呢。
答案就是依靠kotlin特有的特性扩展函数,当然也得益于kotlin对于函数式编程的支持,让koin的代码更加简洁。
将组件注册到容器中后,其原理为将一个组件实例化的方法实例,存储在容器中。

在调用inject()注入的时候,通过组件的定义(单例还是factory),以及绑定的类型(实例化方法绑定到哪个接口或者类型)匹配到对应的生成器(注册的实例化方法),然后通过扩展函数的形式,在Android组件(Activity,Fragment等)中实例化注入。
这里的inject方法是ComponentCallbacks接口的扩展函数,而ComponentCallbacks是所有Android应用组件都继承的几口,所以,能在ComponentCallbacks的实现组件中进行inject注入。
这种新的依赖注入方式,也为我们项目中的架构优化提供了更多的想象空间。
比如对于网络请求,可以让具体的请求方式与业务调用隔离。
这种思想类似于服务开发,只需要向外暴露出使用的接口,具体实现方案调用方并不用关心。

你可能感兴趣的:(Android)