簡介

承續之前的程式碼 (Dependency Injection – 1 – 程式碼範例 – 自行撰寫將 SharedPreferences 實例依賴注入的程式碼),我們使用 Koin 來重構程式。

依賴

libs.versions.toml (修改)

[versions]
...

koin = "3.5.3"

[libraries]
...

koin-core = { group = "io.insert-koin", name = "koin-core", version.ref = "koin" }
koin-android = { group = "io.insert-koin", name = "koin-android", version.ref = "koin" }
koin-androidx-compose = { group = "io.insert-koin", name = "koin-androidx-compose", version.ref = "koin" }

...

[bundles]
...

koin-compose = ["koin-core", "koin-android", "koin-androidx-compose"]

build.gradle.kts (Module level :app) (修改)

...

dependencies {

    ...

    implementation(libs.bundles.koin.compose)

}

程式碼範例

AppModule.kt (修改)

//interface AppModule {
//    val sharedPref: SharedPreferences
//}
//
//class AppModuleImpl( private val appContext: Context): AppModule {
//    override val sharedPref: SharedPreferences = appContext.getSharedPreferences("mypref", Context.MODE_PRIVATE)
//}

val appModule = module {
    // 完整寫法
//    single<SharedPreferences> {
//        androidApplication().getSharedPreferences("mypref", Context.MODE_PRIVATE)
//    }
    // 因為可以從產生的實例類別對應到 MainViewModel 的參數型別,所以可以省略類別
    
    single {
        androidApplication().getSharedPreferences("mypref", Context.MODE_PRIVATE)
    }
    // 但如果我們用的是子類別 (例如: androidx.security.crypto.EncryptedSharedPreferences),
    // 就要指定要注入的類別
//    single<SharedPreferences> {
//        EncryptedSharedPreferences(
//            androidApplication(),
//            "mypref",
//            MasterKey(androidApplication()),
//            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
//            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
//        )
//    }

    viewModel {
        MainViewModel(get())
    }
    // 這種寫法也可以
    // viewModelOf(::MainViewModel)
}

MyApp.kt (修改)

class MyApp: Application() {
//    companion object {
//        lateinit var appModule: AppModule
//    }

    override fun onCreate() {
        super.onCreate()
//        appModule = AppModuleImpl(this)
        
        startKoin {
            androidLogger()  
            androidContext(this@MyApp)
            modules(appModule)
        }
    }
}

MainActivity.kt (修改)

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {

//        val sharedPref = getSharedPreferences("mypref" , Context.MODE_PRIVATE)
//        sharedPref.edit {
//            putString("username", "Mary")
//        }
//        println(sharedPref.getString("username", ""))
//        val username = sharedPref.getString("username", "") ?: ""

//        val viewModel by viewModels<MainViewModel> {
//            MainViewModelFactory(
//                MyApp.appModule.sharedPref
//            )
//        }


        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {

            DILabTheme {
                // 只需要這行
                val viewModel = getViewModel<MainViewModel>()

                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Greeting(
                        name = viewModel.username,
                        modifier = Modifier.padding(innerPadding)
                    )
                }
            }
        }
    }
}

這樣,就完成以 Koin 幫助我們完成依賴注入,執行後,結果如下:

參考資料

Koin Official Site

Koin 的那一兩件事情

Day22 – 依賴注入框架Koin

Last modified: 2025 年 6 月 30 日

Author

Comments

Write a Reply or Comment

Your email address will not be published.