项目工程中之前用的4.1.0版本的Kodein.最近将Kodein升级到6.0.0.主要是工程现在没有适配AndroidX,Kodein6.0以上只找到AndroidX版本的,官网也没有什么历史版本索引,GitHub上文档也使用页面是白的,因此这次先升级到6.0.0。Kodein4.+到6.0的变化比较大,6.0以后变化就不是很大了这里这里记录以下6.0的新的语法调用。
配置依赖
implementation "org.kodein.di:kodein-di-core-jvm:6.0.0"
implementation "org.kodein.di:kodein-di-generic-jvm:6.0.0"
implementation "org.kodein.di:kodein-di-framework-android-support:6.0.0"
配置仓库
repositories {
google()
jcenter()
maven { url 'https://dl.bintray.com/kodein-framework/Kodein-DI/' }
}
推荐的方式:
class App() : Application(), KodeinAware {
override val kodein = Kodein.lazy {
bind<Context>() with singleton { this@App }
bind<AppInfo>() with singleton { appInfo }
import(appModule(applicationContext))
}
override fun onCreate() {
super.onCreate()
}
}
abstract class InjectActivity :AppCompatActivity(),KodeinAware {
private val appKodein by closestKodein()
override val kodein: Kodein by retainedKodein {
// 把app中的注入包含进来
extend(appKodein)
import(baseActivityModule(this@InjectActivity), allowOverride = true)
}
/**
* Optional to override, if your activity needs specific DI.
*/
open fun activityModule() = Kodein.Module("activityModule") {
}
}
fun appModule(appContext: Context) = Kodein.Module("appModule") {
bind<Navigator>() with provider { PhotoAppNavigator(instance()) }
bind<Logger>() with singleton { AndroidLogger() }
bind<Invoker>() with factory{a:String->UseCaseInvoker()}
bind<Invoker>() with factory{a:String,b:Int,c:String,d:String,e:String->UseCaseInvoker()}
import(httpAppModule())
import(photosAppModule())
}
使用的时候:
以下三种方式是等效的
val appinfo = kodein.direct.Instance(TT(AppInfo::class.java))
val appinfo1 by kodein.instance<AppInfo>()
val appinfo2 = kodein.direct.instance<AppInfo>()
factory传参使用如下:
val invoker1 = kodein.direct.factory<String, Invoker>().invoke("我是参数")
val invoker2 = kodein.direct.factory2<String,String, Invoker>().invoke("我是参数1","我是参数2")
// 同理三四五
下面2个也是等效的
val navigator = kodein.direct.provider<Navigator>()
val navigator1 by kodein.provider<Navigator>()
特殊的注入这里做下记录
bind<Invoker>() with multiton { dbName: String ->
UseCaseInvoker(dbName)
}
对应的获取方法
val logger: Logger = kodein.direct.Instance(TT(String::class),TT(Logger::class),arg = "args")
或者
val logger2 = kodein.direct.factory<String, Logger>().invoke("我是参数")
// 看源发现内部是通过binding的类型来区分返回的,所以这里2种方式是没什么区别的
除了上面的方式,还有另外2中懒加载方式初始化注入
class App() : Application(){
override fun onCreate() {
initDI()
super.onCreate()
}
private fun initDI() {
KodeinConfig.addConfig {
bind<Context>() with singleton { this@App }
bind<AppInfo>() with singleton { appInfo }
}
}
val appInfo by lazy {
AppInfo(
BuildConfig.APPLICATION_ID,
metaData("CHECK_VERSION_ID", ""),
Device.PHONE
)
}
}
方式一:
val kodeinExt = LateInitKodein()
object KodeinConfig {
fun addConfig(config: Kodein.Builder.() -> Unit) {
kodeinExt.baseKodein = Kodein.lazy {
import(Kodein.Module("config",init = config))
bind<Logger>() with singleton { AndroidLogger() }
}
}
}
方式二:
val kodeinExt = LazyKodein(){
Kodein.lazy {
bind<Logger>() with singleton { AndroidLogger() }
import(configModule)
}
}
object KodeinConfig {
@Volatile
private var canConfigureBase = true
lateinit var configModule : Kodein.Module
fun addConfig(config: Kodein.Builder.() -> Unit) {
if (canConfigureBase) {
configModule = Kodein.Module("config",init = config)
canConfigureBase = false
}
}
}