当前位置: 首页 > 工具软件 > Koin > 使用案例 >

Koin 注入框架 - Android 使用方法 及 问题记录

凌鹏程
2023-12-01

Koin (可以理解为注入框架),在Android 使用频繁,并且Koin官方专门给Android做了依赖库。

使用起来非常方便。

我们可以通过看官网的例子快速入门。

这里根据官方给出的例子,加上自己的理解和使用过程中遇到的问题, 做了个简单记录。

1. 官网首页
https://insert-koin.io/

2. change log:
https://github.com/InsertKoinIO/koin/blob/main/CHANGELOG.md

3. 快速入门 (Kotlin/Android)

Android | Koin
https://insert-koin.io/docs/quickstart/kotlin

(1) 根目录build.gradle 设置Koin版本
buildscript {
    ext {
        koin_version = "3.2.0"
    }

(2) app/build.gradle 添加koin-android 依赖

dependencies {
    // Koin for Android
    implementation "io.insert-koin:koin-android:$koin_version" //包含了核心库 org.koin.core
}

(3) 创建接口 HelloRepository  / 实现类 HelloRepositoryImpl / 包装类类MySimplePresenter

(4) 声明 koin module , 用于创建单例
val appModule = module {

    // single instance of HelloRepository
    single<HelloRepository> { HelloRepositoryImpl() }

    // Simple Presenter Factory
    factory { MySimplePresenter(get()) }
}

(5) 启动Koin  (在App创建的时候,加载module, 即去创建单例)
class MyApplication : Application(){
    override fun onCreate() {
        super.onCreate()
        // Start Koin
        startKoin{ // @ org.koin.core.context
            androidLogger()
            androidContext(this@MyApplication) //android扩展库 org.koin.android.ext.koin
            modules(appModule) //  org.koin.core.KoinApplication
        }
    }
}

(6) 真正使用 (注入依赖)
 val firstPresenter: MySimplePresenter by inject()
>>> 这里的inject是 org.koin.android.ext.android.inject
(为啥不用 org.koin.java.KoinJavaComponent.inject ???? 专门给android做了封装???) 

4. 在Android中的优势
(1) 非Activity/Service 等想要获取Context 时,可以通过 androidContext(applicationContext) 注入依赖
其它地方则可以通过注入获取,不需要单独创建API 传递Context实例,大大减少代码量和复杂度 
java: Context context = get(Context.class) 或 Lazy<Context> mContext = inject(Context.class) 
Kotlin : val appContext = get<Context>()  或者 val context:Context by inject() 

androidContext实现源码(与自己实现类似: single {XXXX})

fun KoinApplication.androidContext(androidContext: Context): KoinApplication {
    if (koin.logger.isAt(Level.INFO)) {
        koin.logger.info("[init] declare Android Context")
    }

    if (androidContext is Application) {
        koin.loadModules(listOf(module {
            single { androidContext } binds arrayOf(Context::class,Application::class)
        }))
    } else {
        koin.loadModules(listOf(module {
            single{ androidContext }
        }))
    }

    return this
}

附-问题汇总

1. kotlin libraries attached to this project were compiled with a newer kotlin compiler and can't be read ,
please update kotlin plugin
kotlin库附加到这个项目是用更新的kotlin编译器编译的,不能读取,请更新kotlin插件
 

2. 在Java 中通过 inject 延迟注入、 get立刻注入
https://stackoverflow.com/questions/50668797/inject-koin-in-java-classes

用法: inject(类名.class)  / get(类名.class)

// 延迟注入,sizePref.loadHeight error  (赋值给变量,显示调用它的函数会报错)

  Lazy<SizePreference> sizePref =  inject(SizePreference.class); //延迟注入
    SizePreference sizePref = get(SizePreference.class); // 立刻注入

注:需要导入静态方法:import static org.koin.java.KoinJavaComponent.get;

3.  Kotlin 使用inject : SizeProvider: ISizeProvider by inject()
提示:No value passed for parameter 'clazz'
原因: 在Activity 或者 Fragment中使用,需要实现 KoinComponent

解决方法:
所在类 实现KoinComponent ,需要导入这两个包
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject


参考:
https://stackoverflow.com/questions/61260337/trying-to-use-koin-but-doesnt-work-correctly-on-android

延申: java 使用get(类名.class)   kotlin 使用 by inject() ??? 

>>>两种语言都可以使用get 或延迟加载 inject

4. 使用inject时,定义为Lazy, 因为它是延迟加载的
private final Lazy<Context> mContext = inject(Context.class);
使用mContext时,需要 mContext.getValue()

5. java 使用 get(XXX.class) 时,需要强转
例如: ((Context) get(Context.class)).getResources()..
或者:
Context context = get(Context.class); 
context.getResources()...

 类似资料: