Kodein使用记录

    技术2024-12-04  14

    项目工程中之前用的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 } } }
    Processed: 0.036, SQL: 9