koin
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseKoin Skill
Koin 技能文档
Comprehensive assistance with koin development, generated from official documentation.
本技能提供Koin开发的全面指导,内容源自官方文档。
When to Use This Skill
何时使用本技能
This skill should be triggered when:
- Working with koin
- Asking about koin features or APIs
- Implementing koin solutions
- Debugging koin code
- Learning koin best practices
当你遇到以下场景时,可启用本技能:
- 进行Koin相关开发
- 咨询Koin的功能或API
- 实现基于Koin的解决方案
- 调试Koin代码
- 学习Koin的最佳实践
Quick Reference
快速参考
Common Patterns
常见模式
Pattern 1: Koin Annotations InventoryThis document provides a comprehensive inventory of all Koin annotations, their parameters, behaviors, and usage examples.Table of ContentsDefinition Annotations@Single@Factory@ScopedScope Annotations@Scope@ViewModelScope@ActivityScope@ActivityRetainedScope@FragmentScope@ScopeIdViewModel & Android-Specific Annotations@KoinViewModel@KoinWorkerQualifier Annotations@Named@QualifierProperty Annotations@Property@PropertyValueModule & Application Annotations@Module@ComponentScan@Configuration@KoinApplicationMonitoring Annotations@MonitorMeta Annotations (Internal)@ExternalDefinition@MetaDefinition@MetaModule@MetaApplicationDefinition Annotations@SinglePackage: org.koin.core.annotationTarget: CLASS, FUNCTIONDescription: Declares a type or function as a single (singleton) definition in Koin. A single instance is created and shared across the application.Parameters:binds: Array<KClass<>> = [Unit::class] - Explicit types to bind to this definition. Supertypes are automatically detected.createdAtStart: Boolean = false - If true, the instance is created when Koin starts.Behavior: All dependencies are filled by constructor injection.Example:@Singleclass MyClass(val d : MyDependency)Generated Koin DSL:single { MyClass(get()) }With explicit binding:@Single(binds = [MyInterface::class])class MyClass(val d : MyDependency) : MyInterfaceWith creation at start:@Single(createdAtStart = true)class MyClass(val d : MyDependency)@FactoryPackage: org.koin.core.annotationTarget: CLASS, FUNCTIONDescription: Declares a type or function as a factory definition in Koin. A new instance is created each time it is requested.Parameters:binds: Array<KClass<>> = [Unit::class] - Explicit types to bind to this definition. Supertypes are automatically detected.Behavior: All dependencies are filled by constructor injection. Each request creates a new instance.Example:@Factoryclass MyClass(val d : MyDependency)Generated Koin DSL:factory { MyClass(get()) }@ScopedPackage: org.koin.core.annotationTarget: CLASS, FUNCTIONDescription: Declares a type or function as a scoped definition in Koin. Must be associated with @Scope annotation. Instance is shared within a specific scope.Parameters:binds: Array<KClass<>> = [Unit::class] - Explicit types to bind to this definition. Supertypes are automatically detected.Behavior: Creates a scoped instance that lives within the defined scope's lifetime.Example:@Scope(MyScope::class)@Scopedclass MyClass(val d : MyDependency)See Also: @ScopeScope Annotations@ScopePackage: org.koin.core.annotationTarget: CLASS, FUNCTIONDescription: Declares a class in a Koin scope. Scope name is described by either value (class) or name (string). By default, declares a scoped definition. Can be overridden with @Scoped, @Factory, @KoinViewModel annotations for explicit bindings.Parameters:value: KClass<> = Unit::class - Scope class valuename: String = "" - Scope string valueBehavior: Creates a scope definition associated with the specified scope type or name.Example with class:@Scope(MyScope::class)class MyClass(val d : MyDependency)Generated Koin DSL:scope<MyScope> { scoped { MyClass(get()) }}Example with string name:@Scope(name = "my_custom_scope")class MyClass(val d : MyDependency)@ViewModelScopePackage: org.koin.core.annotationTarget: CLASS, FUNCTIONDescription: Declares a class in a ViewModelScope Koin scope. This is a scope archetype for components that should live within a ViewModel's lifecycle.Parameters: NoneBehavior: Creates a scoped definition within the viewModelScope.Example:@ViewModelScopeclass MyClass(val d : MyDependency)Generated Koin DSL:viewModelScope { scoped { MyClass(get()) }}Usage: The tagged class is meant to be used with ViewModel and viewModelScope function to activate the scope.@ActivityScopePackage: org.koin.android.annotationTarget: CLASS, FUNCTIONDescription: Declares a class in an Activity Koin Scope.Parameters: NoneBehavior: Creates a scoped definition within the activityScope.Example:@ActivityScopeclass MyClass(val d : MyDependency)Generated Koin DSL:activityScope { scoped { MyClass(get()) }}Usage: The tagged class is meant to be used with Activity and activityScope function to activate the scope.@ActivityRetainedScopePackage: org.koin.android.annotationTarget: CLASS, FUNCTIONDescription: Declares a class in an Activity Koin scope, but retained across configuration changes.Parameters: NoneBehavior: Creates a scoped definition within the activityRetainedScope.Example:@ActivityRetainedScopeclass MyClass(val d : MyDependency)Generated Koin DSL:activityRetainedScope { scoped { MyClass(get()) }}Usage: The tagged class is meant to be used with Activity and activityRetainedScope function to activate the scope.@FragmentScopePackage: org.koin.android.annotationTarget: CLASS, FUNCTIONDescription: Declares a class in a Fragment Koin scope.Parameters: NoneBehavior: Creates a scoped definition within the fragmentScope.Example:@FragmentScopeclass MyClass(val d : MyDependency)Generated Koin DSL:fragmentScope { scoped { MyClass(get()) }}Usage: The tagged class is meant to be used with Fragment and fragmentScope function to activate the scope.@ScopeIdPackage: org.koin.core.annotationTarget: VALUE_PARAMETERDescription: Annotates a parameter from class constructor or function to request resolution for a given scope with Scope ID.Parameters:value: KClass<> = Unit::class - Scope typename: String = "" - Scope string identifierBehavior: Resolves the dependency from a specific scope identified by type or name.Example with string name:@Factoryclass MyClass(@ScopeId(name = "my_scope_id") val d : MyDependency)Generated Koin DSL:factory { MyClass(getScope("my_scope_id").get()) }Example with type:@Factoryclass MyClass(@ScopeId(MyScope::class) val d : MyDependency)ViewModel & Android-Specific Annotations@KoinViewModelPackage: org.koin.android.annotationTarget: CLASS, FUNCTIONDescription: ViewModel annotation for Koin definition. Declares a type or function as a viewModel definition in Koin.Platform Support:✅ Android✅ Kotlin Multiplatform (KMP)✅ Compose Multiplatform (CMP)Parameters:binds: Array<KClass<>> = [] - Explicit types to bind to this definition. Supertypes are automatically detected.Behavior: All dependencies are filled by constructor injection. Creates a ViewModel instance managed by Koin. Works across all platforms including Android, iOS, Desktop, and Web when using Compose Multiplatform.Example (Android/CMP):@KoinViewModelclass MyViewModel(val d : MyDependency) : ViewModel()Example (KMP/CMP shared):@KoinViewModelclass SharedViewModel( val repository: Repository, val analytics: Analytics) : ViewModel()Generated Koin DSL:viewModel { MyViewModel(get()) }@KoinWorkerPackage: org.koin.android.annotationTarget: CLASS, FUNCTIONDescription: Worker annotation for Koin Definition. Declares a type as a worker definition for WorkManager workers.Parameters:binds: Array<KClass<>> = [] - Explicit types to bind to this definition.Behavior: Creates a worker definition for Android WorkManager integration.Example:@KoinWorkerclass MyWorker() : Worker()Qualifier Annotations@NamedPackage: org.koin.core.annotationTarget: CLASS, FUNCTION, VALUE_PARAMETERDescription: Defines a qualifier for a given definition. Generates StringQualifier("...") or type-based qualifier.Parameters:value: String = "" - String qualifiertype: KClass<> = Unit::class - Class qualifierBehavior: Used to distinguish between multiple definitions of the same type.Example with string:@Single@Named("special")class MyClass(val d : MyDependency)Usage in parameter:@Singleclass Consumer(@Named("special") val myClass: MyClass)Example with type:@Single@Named(type = MyType::class)class MyClass(val d : MyDependency)@QualifierPackage: org.koin.core.annotationTarget: CLASS, FUNCTION, VALUE_PARAMETERDescription: Defines a qualifier for a given definition. Similar to @Named but with reversed parameter priority.Parameters:value: KClass<> = Unit::class - Class qualifiername: String = "" - String qualifierBehavior: Used to distinguish between multiple definitions of the same type.Example:@Single@Qualifier(name = "special")class MyClass(val d : MyDependency)Property Annotations@PropertyPackage: org.koin.core.annotationTarget: VALUE_PARAMETERDescription: Annotates a constructor parameter or function parameter to resolve as a Koin property.Parameters:value: String - Property nameBehavior: Resolves the parameter value from Koin properties instead of dependency injection.Example:@Factoryclass MyClass(@Property("name") val name : String)Generated Koin DSL:factory { MyClass(getProperty("name")) }With default value:@PropertyValue("name")val defaultName = "MyName"@Factoryclass MyClass(@Property("name") val name : String)Generated Koin DSL:factory { MyClass(getProperty("name", defaultName)) }@PropertyValuePackage: org.koin.core.annotationTarget: FIELDDescription: Annotates a field value that will be a Property default value.Parameters:value: String - Property nameBehavior: Defines a default value for a property that can be used when the property is not found.Example:@PropertyValue("name")val defaultName = "MyName"@Factoryclass MyClass(@Property("name") val name : String)Generated Koin DSL:factory { MyClass(getProperty("name", defaultName)) }Module & Application Annotations@ModulePackage: org.koin.core.annotationTarget: CLASSDescription: Class annotation to help gather definitions inside a Koin module. Each function can be annotated with a Koin definition annotation.Parameters:includes: Array<KClass<>> = [] - Module classes to includecreatedAtStart: Boolean = false - If true, module instances are created at startBehavior: Gathers all annotated functions and classes within the module.Example:@Moduleclass MyModule { @Single fun myClass(d : MyDependency) = MyClass(d)}Generated Koin DSL:val MyModule.module = module { val moduleInstance = MyModule() single { moduleInstance.myClass(get()) }}With includes:@Module(includes = [OtherModule::class])class MyModule { // definitions}@ComponentScanPackage: org.koin.core.annotationTarget: CLASS, FIELDDescription: Gathers definitions declared with Koin definition annotations. Scans current package or explicit package names.Parameters:value: vararg String = [] - Packages to scan (supports glob patterns)Behavior: Scans specified packages for annotated classes. Supports both exact package names and glob patterns.Glob Pattern Support:Exact package names (no wildcards):com.example.service - Scans package and all subpackages (equivalent to com.example**)Multi-level scan including root:com.example** - Scans com.example and all subpackagesMulti-level scan excluding root:com.example.** - Scans only subpackages of com.example, excludes rootSingle-level wildcard:com.example..service - Matches exactly one level (e.g., com.example.user.service)Combined wildcards:com..service.data - Complex pattern matchingcom..service. - Scans subpackages under patternExample - scan current package:@ComponentScanclass MyAppExample - scan specific packages:@ComponentScan("com.example.services", "com.example.repositories")class MyAppExample - with glob patterns:@ComponentScan("com.example.**", "org.app..services")class MyApp@ConfigurationPackage: org.koin.core.annotationTarget: CLASS, FIELDDescription: Applied to @Module class to associate it with one or more configurations (tags/flavors).Parameters:value: vararg String = [] - Configuration namesBehavior: Modules can be grouped into configurations for conditional loading.Default Configuration:@Module@Configurationclass MyModuleThis module is part of the "default" configuration.Multiple Configurations:@Module@Configuration("prod", "test")class MyModuleThis module is available in both "prod" and "test" configurations.With Default:@Module@Configuration("default", "test")class MyModuleAvailable in default and test configurations.Note: @Configuration("default") is equivalent to @Configuration@KoinApplicationPackage: org.koin.core.annotationTarget: CLASSDescription: Tags a class as a Koin application entry point. Generates Koin application bootstrap with startKoin() or koinApplication() functions.Parameters:configurations: Array<String> = [] - List of configuration names to scanmodules: Array<KClass<*>> = [Unit::class] - List of modules to load besides configurationsBehavior: Generates bootstrap functions that scan for configurations and included modules.Example - default configuration:@KoinApplicationclass MyAppGenerated functions:MyApp.startKoin()MyApp.koinApplication()Example - specific configurations:@KoinApplication(configurations = ["default", "prod"])class MyAppExample - with modules:@KoinApplication( configurations = ["default"], modules = [CoreModule::class, ApiModule::class])class MyAppUsage with custom configuration:MyApp.startKoin { printLogger() // additional configuration}Monitoring Annotations@MonitorPackage: org.koin.core.annotationTarget: CLASS, FUNCTIONDescription: Marks a class or function for automatic monitoring and performance tracing through Kotzilla Platform, the official tooling platform for Koin.Parameters: NoneBehavior:When applied to a class: Generates a Koin proxy that monitors all public method callsWhen applied to a function: Monitors that specific method within a Koin-managed componentAutomatically captures performance metrics, error rates, and usage patternsSends data to Kotzilla workspace for real-time analysisRequirements:implementation 'io.kotzilla:kotzilla-core:latest.version'Valid Kotzilla Platform account and API keyExample:@Monitorclass UserService(private val userRepository: UserRepository) { fun findUser(id: String): User? = userRepository.findById(id)}Resources:Kotzilla PlatformComplete DocumentationLatest VersionSince: Kotzilla 1.2.1Meta Annotations (Internal)These annotations are for internal use only by the Koin compiler and code generation.@ExternalDefinitionPackage: org.koin.meta.annotationsTarget: CLASS, FIELD, FUNCTIONDescription: Internal usage for components discovery in generated package.Parameters:value: String = "" - Package of declared definition@MetaDefinitionPackage: org.koin.meta.annotationsTarget: CLASS, FUNCTION, PROPERTYDescription: Meta Definition annotation to help represent definition metadata.Parameters:value: String = "" - Definition full pathmoduleTagId: String = "" - Module Tag + ID (format: "module_id:module_tag")dependencies: Array<String> = [] - Parameters tags to checkbinds: Array<String> = [] - Bound typesqualifier: String = "" - Qualifierscope: String = "" - Scope where it's declared@MetaModulePackage: org.koin.meta.annotationsTarget: CLASSDescription: Meta Module annotation to help represent module metadata.Parameters:value: String = "" - Module full pathid: String = "" - Module IDincludes: Array<String> = [] - Includes Module Tags to checkconfigurations: Array<String> = [] - Module Configurations to checkisObject: Boolean = false - Whether the module is an object@MetaApplicationPackage: org.koin.meta.annotationsTarget: CLASSDescription: Meta Application annotation to help represent application metadata.Parameters:value: String = "" - Application full pathincludes: Array<String> = [] - Used Module Tags to checkconfigurations: Array<String> = [] - Used Configurations modules to checkDeprecated Annotations@SingletonPackage: org.koin.core.annotationStatus: DEPRECATED - ERROR levelReplacement: Use @Singleton from koin-jsr330 package insteadDescription: Same as @Single but deprecated in favor of JSR-330 compliance.Summary TableAnnotationPackagePurposeCommon Use Case@Singleorg.koin.core.annotationSingleton definitionShared application services@Factoryorg.koin.core.annotationFactory definitionPer-request instances@Scopedorg.koin.core.annotationScoped definitionScope-specific instances@Scopeorg.koin.core.annotationScope declarationCustom scopes@ViewModelScopeorg.koin.core.annotationViewModel scopeViewModel-scoped dependencies@ActivityScopeorg.koin.android.annotationActivity scopeActivity-scoped dependencies@ActivityRetainedScopeorg.koin.android.annotationRetained activity scopeConfig-change surviving deps@FragmentScopeorg.koin.android.annotationFragment scopeFragment-scoped dependencies@ScopeIdorg.koin.core.annotationScope resolutionResolve from specific scope@KoinViewModelorg.koin.android.annotationViewModel definitionAndroid/KMP/CMP ViewModels@KoinWorkerorg.koin.android.annotationWorker definitionWorkManager workers@Namedorg.koin.core.annotationString/type qualifierDistinguish same-type beans@Qualifierorg.koin.core.annotationType/string qualifierDistinguish same-type beans@Propertyorg.koin.core.annotationProperty injectionConfiguration values@PropertyValueorg.koin.core.annotationProperty defaultDefault config values@Moduleorg.koin.core.annotationModule declarationGroup definitions@ComponentScanorg.koin.core.annotationPackage scanningAuto-discover definitions@Configurationorg.koin.core.annotationModule configurationBuild variants/flavors@KoinApplicationorg.koin.core.annotationApp entry pointBootstrap Koin@Monitororg.koin.core.annotationPerformance monitoringProduction monitoringDocument Version: 1.0 Last Updated: 20-10-2025 Koin Annotations Version: 2.2.x+
org.koin.core.annotationPattern 2: Example:
@Singleclass MyClass(val d : MyDependency)Pattern 3: Example:
@Factoryclass MyClass(val d : MyDependency)Pattern 4: Example:
@Scope(MyScope::class)@Scopedclass MyClass(val d : MyDependency)Pattern 5: Example:
@ViewModelScopeclass MyClass(val d : MyDependency)Pattern 6: Why Koin?Koin provides an easy and efficient way to incorporate dependency injection into any Kotlin application(Multiplatform, Android, backend ...)The goals of Koin are:Simplify your Dependency Injection infrastructure with smart APIKotlin DSL easy to read, easy to use, to let you write any kind of application Provides different kind of integration from Android ecosystem, to more backend needs like KtorAllow to be used with annotations Koin in a nutshellMaking your Kotlin development easy and productiveKoin is a smart Kotlin dependency injection library to keep you focused on your app, not on your tools.class MyRepository()class MyPresenter(val repository : MyRepository) // just declare it val myModule = module { singleOf(::MyPresenter) singleOf(::MyRepository)}Koin gives you simple tools and API to let you build, assemble Kotlin related technologies into your application and let you scale your business with easiness.fun main() { // Just start Koin startKoin { modules(myModule) }} Ready for AndroidThanks to the Kotlin language, Koin extends the Android platform and provides new features as part of the original platform.class MyApplication : Application() { override fun onCreate() { super.onCreate() startKoin { modules(myModule) } } }Koin provides easy and powerful API to retrieve your dependencies anywhere in Android components, with just using by inject() or by viewModel()class MyActivity : AppCompatActivity() { val myPresenter : MyPresenter by inject()} Powering Kotlin MultiplatformSharing code between mobile platforms is one of the major Kotlin Multiplatform use cases. With Kotlin Multiplatform Mobile, you can build cross-platform mobile applications and share common code between Android and iOS.Koin provides multiplatform dependency injection and help build your components across your native mobile applications, and web/backend applications.Performances and ProductivityKoin is a pure Kotlin framework, designed to be straight forward in terms of usage and execution. It easy to use and doesn't impact your compilation time, nor require any extra plugin configuration.Koin: A Dependency Injection FrameworkKoin is a popular dependency injection (DI) framework for Kotlin, offering a modern and lightweight solution for managing your application’s dependencies with minimal boilerplate code.Dependency Injection vs. Service LocatorWhile Koin may appear similar to a service locator pattern, there are key differences that set it apart:Service Locator: A service locator is essentially a registry of available services where you can request an instance of a service as needed. It is responsible for creating and managing these instances, often using a static, global registry.Dependency Injection: In contrast, Koin is a pure dependency injection framework. With Koin, you declare your dependencies in modules, and Koin handles the creation and wiring of objects. It allows for the creation of multiple, independent modules with their own scopes, making dependency management more modular and avoiding potential conflicts.Koin’s Approach: A Blend of Flexibility and Best PracticesKoin supports both DI and the Service Locator pattern, offering flexibility to developers. However, it strongly encourages the use of DI, particularly constructor injection, where dependencies are passed as constructor parameters. This approach promotes better testability and makes your code easier to reason about.Koin’s design philosophy is centered around simplicity and ease of setup while allowing for complex configurations when necessary. By using Koin, developers can manage dependencies effectively, with DI being the recommended and preferred approach for most scenarios.Transparency and Design OverviewKoin is designed to be a versatile Inversion of Control (IoC) container that supports both Dependency Injection (DI) and Service Locator (SL) patterns. To provide a clear understanding of how Koin operates and to guide you in using it effectively, let’s explore the following aspects:How Koin Balances DI and SLKoin combines elements of both DI and SL, which may influence how you use the framework:Global Context Usage: By default, Koin provides a globally accessible component that acts like a service locator. This allows you to retrieve dependencies from a central registry using KoinComponent or inject functions.Isolated Components: Although Koin encourages the use of Dependency Injection, particularly constructor injection, it also allows for isolated components. This flexibility means you can configure your application to use DI where it makes the most sense while still taking advantage of SL for specific cases.SL in Android Components: In Android development, Koin often uses SL internally within components such as Application and Activity for ease of setup. From this point, Koin recommends DI, especially constructor injection, to manage dependencies in a more structured way. However, this is not enforced, and developers have the flexibility to use SL if needed.Why This Matters to YouUnderstanding the distinction between DI and SL helps in managing your application’s dependencies effectively:Dependency Injection: Encouraged by Koin for its benefits in testability and maintainability. Constructor injection is preferred as it makes dependencies explicit and enhances code clarity.Service Locator: While Koin supports SL for convenience, especially in Android components, relying solely on SL can lead to tighter coupling and reduced testability. Koin’s design provides a balanced approach, allowing you to use SL where it’s practical but promoting DI as the best practice.Making the Most of KoinTo use Koin effectively:Follow Best Practices: Use constructor injection where possible to align with best practices for dependency management. This approach improves testability and maintainability.Leverage Koin’s Flexibility: Utilize Koin’s support for SL in scenarios where it simplifies setup, but aim to rely on DI for managing core application dependencies.Refer to Documentation and Examples: Review Koin’s documentation and examples to understand how to configure and use DI and SL appropriately based on your project needs.Visualize Dependency Management: Diagrams and examples can help illustrate how Koin resolves dependencies and manages them within different contexts. These visual aids can provide a clearer understanding of Koin’s internal workings.By providing this guidance, we aim to help you navigate Koin’s features and design choices effectively, ensuring you can leverage its full potential while adhering to best practices in dependency management.
class MyRepository()class MyPresenter(val repository : MyRepository) // just declare it val myModule = module { singleOf(::MyPresenter) singleOf(::MyRepository)}Pattern 7: Global Context Usage: By default, Koin provides a globally accessible component that acts like a service locator. This allows you to retrieve dependencies from a central registry using KoinComponent or inject functions.
KoinComponentPattern 8: DefinitionsBy using Koin, you describe definitions in modules. In this section we will see how to declare, organize & link your modules.Writing a moduleA Koin module is the space to declare all your components. Use the module function to declare a Koin module:val myModule = module { // your dependencies here}In this module, you can declare components as described below.Defining a singletonDeclaring a singleton component means that Koin container will keep a unique instance of your declared component. Use the single function in a module to declare a singleton:class MyService()val myModule = module { // declare single instance for MyService class single { MyService() }}Defining your component within a lambdasingle, factory & scoped keywords help you declare your components through a lambda expression. this lambda describe the way that you build your component. Usually we instantiate components via their constructors, but you can also use any expression.single { Class constructor // Kotlin expression }The result type of your lambda is the main type of your componentDefining a factoryA factory component declaration is a definition that will provide you a new instance each time you ask for this definition (this instance is not retained by Koin container, as it won't inject this instance in other definitions later). Use the factory function with a lambda expression to build a component.class Controller()val myModule = module { // declare factory instance for Controller class factory { Controller() }}info Koin container doesn't retain factory instances as it will give a new instance each time the definition is asked.Resolving & injecting dependenciesNow that we can declare components definitions, we want to link instances with dependency injection. To resolve an instance in a Koin module, just use the get() function to request the needed component instance. This get() function is usually used into constructor, to inject constructor values.info To make dependency injection with Koin container, we have to write it in constructor injection style: resolve dependencies in class constructors. This way, your instance will be created with injected instances from Koin.Let's take an example with several classes:// Presenter <- Serviceclass Service()class Controller(val view : View)val myModule = module { // declare Service as single instance single { Service() } // declare Controller as single instance, resolving View instance with get() single { Controller(get()) }}Definition: binding an interfaceA single or a factory definition use the type from their given lambda definition i.e: single { T } The matched type of the definition is the only matched type from this expression.Let's take an example with a class and implemented interface:// Service interfaceinterface Service{ fun doSomething()}// Service Implementationclass ServiceImp() : Service { fun doSomething() { ... }}In a Koin module we can use the as cast Kotlin operator as follows:val myModule = module { // Will match type ServiceImp only single { ServiceImp() } // Will match type Service only single { ServiceImp() as Service }}You can also use the inferred type expression:val myModule = module { // Will match type ServiceImp only single { ServiceImp() } // Will match type Service only single<Service> { ServiceImp() }}note This 2nd way of style declaration is preferred and will be used for the rest of the documentation.Additional type bindingIn some cases, we want to match several types from just one definition.Let's take an example with a class and interface:// Service interfaceinterface Service{ fun doSomething()}// Service Implementationclass ServiceImp() : Service{ fun doSomething() { ... }}To make a definition bind additional types, we use the bind operator with a class:val myModule = module { // Will match types ServiceImp & Service single { ServiceImp() } bind Service::class}Note here, that we would resolve the Service type directly with get(). But if we have multiple definitions binding Service, we have to use the bind<>() function.Definition: naming & default bindingsYou can specify a name to your definition, to help you distinguish two definitions about the same type:Just request your definition with its name:val myModule = module { single<Service>(named("default")) { ServiceImpl() } single<Service>(named("test")) { ServiceImpl() }}val service : Service by inject(qualifier = named("default"))get() and by inject() functions let you specify a definition name if needed. This name is a qualifier produced by the named() function.By default, Koin will bind a definition by its type or by its name, if the type is already bound to a definition.val myModule = module { single<Service> { ServiceImpl1() } single<Service>(named("test")) { ServiceImpl2() }}Then:val service : Service by inject() will trigger the ServiceImpl1 definitionval service : Service by inject(named("test")) will trigger the ServiceImpl2 definitionDeclaring injection parametersIn any definition, you can use injection parameters: parameters that will be injected and used by your definition:class Presenter(val view : View)val myModule = module { single{ (view : View) -> Presenter(view) }}In contrary to resolved dependencies (resolved with get()), injection parameters are parameters passed through the resolution API. This means that those parameters are values passed with get() and by inject(), with the parametersOf function:val presenter : Presenter by inject { parametersOf(view) }Further reading in the Injection Parameters SectionDefinition Termination - OnCloseYou can use the onClose function, to add on a definition, the callback once definition closing is called:class Presenter(val view : View)val myModule = module { factory { (view : View) -> Presenter(view) } onClose { // closing callback - it is Presenter }}Using definition flagsKoin DSL also proposes some flags.Create instances at startA definition or a module can be flagged as CreatedAtStart, to be created at start (or when you want). First set the createdAtStart flag on your module or on your definition.CreatedAtStart flag on a definitionval myModuleA = module { single<Service> { ServiceImp() }}val myModuleB = module { // eager creation for this definition single<Service>(createdAtStart=true) { TestServiceImp() }}CreatedAtStart flag on a module:val myModuleA = module { single<Service> { ServiceImp() }}val myModuleB = module(createdAtStart=true) { single<Service>{ TestServiceImp() }}The startKoin function will automatically create definitions instances flagged with createdAtStart.// Start Koin modulesstartKoin { modules(myModuleA,myModuleB)}infoif you need to load some definition at a special time (in a background thread instead of UI for example), just get/inject the desired components.Explicit override per definition (4.2.0+)When you have allowOverride(false) enabled for strict control, but need specific definitions to override existing ones, you can use the .override() option:val productionModule = module { single<Service> { ProductionService() }}val testModule = module { // Explicitly mark this definition as allowed to override single<Service> { MockService() }.override()}startKoin { allowOverride(false) // Strict mode modules(productionModule, testModule)}You can also use it with withOptions:single<Service> { MockService() } withOptions { override()}This is particularly useful for:Test configurations that need to override production servicesFeature flags that conditionally override implementationsPlugin systems where specific plugins can override defaultsSee Modules - Explicit Override for more details.Dealing with genericsKoin definitions doesn't take in accounts generics type argument. For example, the module below tries to define 2 definitions of List:module { single { ArrayList<Int>() } single { ArrayList<String>() }}Koin won't start with such definitions, understanding that you want to override one definition for the other.To allow you, use the 2 definitions you will have to differentiate them via their name, or location (module). For example:module { single(named("Ints")) { ArrayList<Int>() } single(named("Strings")) { ArrayList<String>() }}
module模式1:Koin 注解清单
本文档全面汇总了所有Koin注解、它们的参数、行为及使用示例。
目录
定义注解
@Single
@Factory
@Scoped
范围注解
@Scope
@ViewModelScope
@ActivityScope
@ActivityRetainedScope
@FragmentScope
@ScopeId
ViewModel与Android专属注解
@KoinViewModel
@KoinWorker
限定符注解
@Named
@Qualifier
属性注解
@property
@PropertyValue
模块与应用注解
@Module
@ComponentScan
@Configuration
@KoinApplication
监控注解
@Monitor
元注解(内部使用)
@ExternalDefinition
@MetaDefinition
@MetaModule
@MetaApplication
定义注解
@Single
包路径:org.koin.core.annotation
目标:CLASS, FUNCTION
描述:将类型或函数声明为Koin中的单例(singleton)定义。该定义会创建一个实例,并在整个应用中共享。
参数:
binds: Array<KClass<*>> = [Unit::class] - 要绑定到该定义的显式类型,父类型会被自动检测。
createdAtStart: Boolean = false - 如果为true,实例会在Koin启动时创建。
行为:所有依赖通过构造函数注入填充。
示例:
@Single
class MyClass(val d : MyDependency)
生成的Koin DSL:
single { MyClass(get()) }
带显式绑定的示例:
@Single(binds = [MyInterface::class])
class MyClass(val d : MyDependency) : MyInterface
带启动时创建的示例:
@Single(createdAtStart = true)
class MyClass(val d : MyDependency)
@Factory
包路径:org.koin.core.annotation
目标:CLASS, FUNCTION
描述:将类型或函数声明为Koin中的工厂定义。每次请求时都会创建新实例。
参数:
binds: Array<KClass<*>> = [Unit::class] - 要绑定到该定义的显式类型,父类型会被自动检测。
行为:所有依赖通过构造函数注入填充,每次请求都会生成新实例。
示例:
@Factory
class MyClass(val d : MyDependency)
生成的Koin DSL:
factory { MyClass(get()) }
@Scoped
包路径:org.koin.core.annotation
目标:CLASS, FUNCTION
描述:将类型或函数声明为Koin中的作用域定义,必须与@Scope注解关联使用。实例会在特定作用域内共享。
参数:
binds: Array<KClass<*>> = [Unit::class] - 要绑定到该定义的显式类型,父类型会被自动检测。
行为:创建一个在定义的作用域生命周期内存在的作用域实例。
示例:
@Scope(MyScope::class)
@Scoped
class MyClass(val d : MyDependency)
另见:@Scope
范围注解
@Scope
包路径:org.koin.core.annotation
目标:CLASS, FUNCTION
描述:在Koin作用域中声明一个类。作用域名称可通过value(类)或name(字符串)指定。默认情况下会声明一个作用域定义,可通过@Scoped、@Factory、@KoinViewModel注解覆盖以实现显式绑定。
参数:
value: KClass<*> = Unit::class - 作用域类值
name: String = "" - 作用域字符串值
行为:创建与指定作用域类型或名称关联的作用域定义。
类值示例:
@Scope(MyScope::class)
class MyClass(val d : MyDependency)
生成的Koin DSL:
scope<MyScope> { scoped { MyClass(get()) }}
字符串名称示例:
@Scope(name = "my_custom_scope")
class MyClass(val d : MyDependency)
@ViewModelScope
包路径:org.koin.core.annotation
目标:CLASS, FUNCTION
描述:在ViewModelScope Koin作用域中声明一个类。这是适用于应在ViewModel生命周期内存在的组件的作用域原型。
参数:无
行为:在viewModelScope内创建作用域定义。
示例:
@ViewModelScope
class MyClass(val d : MyDependency)
生成的Koin DSL:
viewModelScope { scoped { MyClass(get()) }}
用法:标记的类需与ViewModel和viewModelScope函数配合使用以激活作用域。
@ActivityScope
包路径:org.koin.android.annotation
目标:CLASS, FUNCTION
描述:在Activity Koin作用域中声明一个类。
参数:无
行为:在activityScope内创建作用域定义。
示例:
@ActivityScope
class MyClass(val d : MyDependency)
生成的Koin DSL:
activityScope { scoped { MyClass(get()) }}
用法:标记的类需与Activity和activityScope函数配合使用以激活作用域。
@ActivityRetainedScope
包路径:org.koin.android.annotation
目标:CLASS, FUNCTION
描述:在Activity Koin作用域中声明一个类,但会在配置变更时保留。
参数:无
行为:在activityRetainedScope内创建作用域定义。
示例:
@ActivityRetainedScope
class MyClass(val d : MyDependency)
生成的Koin DSL:
activityRetainedScope { scoped { MyClass(get()) }}
用法:标记的类需与Activity和activityRetainedScope函数配合使用以激活作用域。
@FragmentScope
包路径:org.koin.android.annotation
目标:CLASS, FUNCTION
描述:在Fragment Koin作用域中声明一个类。
参数:无
行为:在fragmentScope内创建作用域定义。
示例:
@FragmentScope
class MyClass(val d : MyDependency)
生成的Koin DSL:
fragmentScope { scoped { MyClass(get()) }}
用法:标记的类需与Fragment和fragmentScope函数配合使用以激活作用域。
@ScopeId
包路径:org.koin.core.annotation
目标:VALUE_PARAMETER
描述:注解类构造函数或函数中的参数,以请求通过Scope ID解析指定作用域的依赖。
参数:
value: KClass<*> = Unit::class - 作用域类型
name: String = "" - 作用域字符串标识符
行为:从通过类型或名称标识的特定作用域中解析依赖。
字符串名称示例:
@Factory
class MyClass(@ScopeId(name = "my_scope_id") val d : MyDependency)
生成的Koin DSL:
factory { MyClass(getScope("my_scope_id").get()) }
类型示例:
@Factory
class MyClass(@ScopeId(MyScope::class) val d : MyDependency)
ViewModel与Android专属注解
@KoinViewModel
包路径:org.koin.android.annotation
目标:CLASS, FUNCTION
描述:用于Koin定义的ViewModel注解。将类型或函数声明为Koin中的viewModel定义。
平台支持:
✅ Android
✅ Kotlin Multiplatform (KMP)
✅ Compose Multiplatform (CMP)
参数:
binds: Array<KClass<*>> = [] - 要绑定到该定义的显式类型,父类型会被自动检测。
行为:所有依赖通过构造函数注入填充。创建由Koin管理的ViewModel实例,支持包括Android、iOS、桌面端和Web端在内的所有平台(使用Compose Multiplatform时)。
示例(Android/CMP):
@KoinViewModel
class MyViewModel(val d : MyDependency) : ViewModel()
示例(KMP/CMP共享):
@KoinViewModel
class SharedViewModel( val repository: Repository, val analytics: Analytics) : ViewModel()
生成的Koin DSL:
viewModel { MyViewModel(get()) }
@KoinWorker
包路径:org.koin.android.annotation
目标:CLASS, FUNCTION
描述:用于Koin定义的Worker注解。将类型声明为WorkManager workers的worker定义。
参数:
binds: Array<KClass<*>> = [] - 要绑定到该定义的显式类型。
行为:为Android WorkManager集成创建worker定义。
示例:
@KoinWorker
class MyWorker() : Worker()
限定符注解
@Named
包路径:org.koin.core.annotation
目标:CLASS, FUNCTION, VALUE_PARAMETER
描述:为给定定义定义限定符,生成StringQualifier("...")或基于类型的限定符。
参数:
value: String = "" - 字符串限定符
type: KClass<*> = Unit::class - 类限定符
行为:用于区分同一类型的多个定义。
字符串示例:
@Single
@Named("special")
class MyClass(val d : MyDependency)
参数中使用示例:
@Single
class Consumer(@Named("special") val myClass: MyClass)
类型示例:
@Single
@Named(type = MyType::class)
class MyClass(val d : MyDependency)
@Qualifier
包路径:org.koin.core.annotation
目标:CLASS, FUNCTION, VALUE_PARAMETER
描述:为给定定义定义限定符,与@Named类似但参数优先级相反。
参数:
value: KClass<*> = Unit::class - 类限定符
name: String = "" - 字符串限定符
行为:用于区分同一类型的多个定义。
示例:
@Single
@Qualifier(name = "special")
class MyClass(val d : MyDependency)
属性注解
@property
包路径:org.koin.core.annotation
目标:VALUE_PARAMETER
描述:注解构造函数参数或函数参数,将其解析为Koin属性。
参数:
value: String - 属性名称
行为:从Koin属性中解析参数值,而非通过依赖注入。
示例:
@Factory
class MyClass(@Property("name") val name : String)
生成的Koin DSL:
factory { MyClass(getProperty("name")) }
带默认值的示例:
@PropertyValue("name")
val defaultName = "MyName"
@Factory
class MyClass(@Property("name") val name : String)
生成的Koin DSL:
factory { MyClass(getProperty("name", defaultName)) }
@PropertyValue
包路径:org.koin.core.annotation
目标:FIELD
描述:注解将作为属性默认值的字段值。
参数:
value: String - 属性名称
行为:为属性定义默认值,当未找到该属性时使用。
示例:
@PropertyValue("name")
val defaultName = "MyName"
@Factory
class MyClass(@Property("name") val name : String)
生成的Koin DSL:
factory { MyClass(getProperty("name", defaultName)) }
模块与应用注解
@Module
包路径:org.koin.core.annotation
目标:CLASS
描述:类注解,用于在Koin模块中收集定义。每个函数可使用Koin定义注解标记。
参数:
includes: Array<KClass<*>> = [] - 要包含的模块类
createdAtStart: Boolean = false - 如果为true,模块实例会在启动时创建
行为:收集模块内所有带注解的函数和类。
示例:
@Module
class MyModule { @Single fun myClass(d : MyDependency) = MyClass(d)}
生成的Koin DSL:
val MyModule.module = module { val moduleInstance = MyModule() single { moduleInstance.myClass(get()) }}
带包含的示例:
@Module(includes = [OtherModule::class])
class MyModule { // 定义 }
@ComponentScan
包路径:org.koin.core.annotation
目标:CLASS, FIELD
描述:收集使用Koin定义注解声明的定义,扫描当前包或指定包名。
参数:
value: vararg String = [] - 要扫描的包(支持通配符模式)
行为:扫描指定包中带注解的类,支持精确包名和通配符模式。
通配符模式支持:
精确包名(无通配符):
com.example.service - 扫描该包及所有子包(等同于com.example**)
包含根目录的多级扫描:
com.example** - 扫描com.example及所有子包
排除根目录的多级扫描:
com.example.** - 仅扫描com.example的子包
单级通配符:
com.example.*.service - 匹配恰好一级(如com.example.user.service)
组合通配符:
com..service.data - 复杂模式匹配
com..service. - 扫描模式下的子包
示例 - 扫描当前包:
@ComponentScan
class MyApp
示例 - 扫描指定包:
@ComponentScan("com.example.services", "com.example.repositories")
class MyApp
示例 - 使用通配符模式:
@ComponentScan("com.example.**", "org.app.*.services")
class MyApp
@Configuration
包路径:org.koin.core.annotation
目标:CLASS, FIELD
描述:应用于@Module类,将其与一个或多个配置(标签/变体)关联。
参数:
value: vararg String = [] - 配置名称
行为:模块可分组为配置以实现条件加载。
默认配置:
@Module
@Configuration
class MyModule
该模块属于"default"配置。
多配置示例:
@Module
@Configuration("prod", "test")
class MyModule
该模块可在"prod"和"test"配置中使用。
带默认配置的示例:
@Module
@Configuration("default", "test")
class MyModule
可在默认和test配置中使用。
注意:@Configuration("default")等同于@Configuration
@KoinApplication
包路径:org.koin.core.annotation
目标:CLASS
描述:将类标记为Koin应用入口点,生成带startKoin()或koinApplication()函数的Koin应用引导代码。
参数:
configurations: Array<String> = [] - 要扫描的配置名称列表
modules: Array<KClass<*>> = [Unit::class] - 除配置外要加载的模块列表
行为:生成扫描配置和包含模块的引导函数。
示例 - 默认配置:
@KoinApplication
class MyApp
生成的函数:
MyApp.startKoin()
MyApp.koinApplication()
示例 - 指定配置:
@KoinApplication(configurations = ["default", "prod"])
class MyApp
示例 - 带模块:
@KoinApplication( configurations = ["default"], modules = [CoreModule::class, ApiModule::class])
class MyApp
自定义配置用法:
MyApp.startKoin { printLogger() // 额外配置 }
监控注解
@Monitor
包路径:org.koin.core.annotation
目标:CLASS, FUNCTION
描述:标记类或函数以通过Kotzilla Platform(Koin官方工具平台)实现自动监控和性能追踪。
参数:无
行为:
应用于类时:生成Koin代理,监控所有公共方法调用
应用于函数时:监控Koin管理组件中的特定方法
自动捕获性能指标、错误率和使用模式
将数据发送到Kotzilla工作区进行实时分析
要求:
implementation 'io.kotzilla:kotzilla-core:latest.version'
有效的Kotzilla Platform账户和API密钥
示例:
@Monitor
class UserService(private val userRepository: UserRepository) { fun findUser(id: String): User? = userRepository.findById(id)}
资源:
Kotzilla Platform
完整文档
最新版本
始于:Kotzilla 1.2.1
元注解(内部使用)
这些注解仅由Koin编译器和代码生成工具内部使用。
@ExternalDefinition
包路径:org.koin.meta.annotations
目标:CLASS, FIELD, FUNCTION
描述:用于在生成包中发现组件的内部注解。
参数:
value: String = "" - 声明定义的包
@MetaDefinition
包路径:org.koin.meta.annotations
目标:CLASS, FUNCTION, PROPERTY
描述:元定义注解,用于表示定义元数据。
参数:
value: String = "" - 定义完整路径
moduleTagId: String = "" - 模块标签+ID(格式:"module_id:module_tag")
dependencies: Array<String> = [] - 要检查的参数标签
binds: Array<String> = [] - 绑定类型
qualifier: String = "" - 限定符
scope: String = "" - 声明的作用域
@MetaModule
包路径:org.koin.meta.annotations
目标:CLASS
描述:元模块注解,用于表示模块元数据。
参数:
value: String = "" - 模块完整路径
id: String = "" - 模块ID
includes: Array<String> = [] - 要检查的包含模块标签
configurations: Array<String> = [] - 要检查的模块配置
isObject: Boolean = false - 模块是否为对象
@MetaApplication
包路径:org.koin.meta.annotations
目标:CLASS
描述:元应用注解,用于表示应用元数据。
参数:
value: String = "" - 应用完整路径
includes: Array<String> = [] - 要检查的使用模块标签
configurations: Array<String> = [] - 要检查的使用配置模块
已废弃注解
@Singleton
包路径:org.koin.core.annotation
状态:已废弃 - 错误级别
替代方案:使用koin-jsr330包中的@Singleton
描述:与@Single功能相同,但为了兼容JSR-330而被废弃。
摘要表
注解 包路径 用途 常见场景
@Single org.koin.core.annotation 单例定义 共享应用服务
@Factory org.koin.core.annotation 工厂定义 每次请求的实例
@Scoped org.koin.core.annotation 作用域定义 特定作用域的实例
@Scope org.koin.core.annotation 作用域声明 自定义作用域
@ViewModelScope org.koin.core.annotation ViewModel作用域 ViewModel作用域依赖
@ActivityScope org.koin.android.annotation Activity作用域 Activity作用域依赖
@ActivityRetainedScope org.koin.android.annotation 保留的Activity作用域 配置变更后存活的依赖
@FragmentScope org.koin.android.annotation Fragment作用域 Fragment作用域依赖
@ScopeId org.koin.core.annotation 作用域解析 从特定作用域解析
@KoinViewModel org.koin.android.annotation ViewModel定义 Android/KMP/CMP ViewModels
@KoinWorker org.koin.android.annotation Worker定义 WorkManager workers
@Named org.koin.core.annotation 字符串/类型限定符 区分同类型bean
@Qualifier org.koin.core.annotation 类型/字符串限定符 区分同类型bean
@property org.koin.core.annotation 属性注入 配置值
@PropertyValue org.koin.core.annotation 属性默认值 默认配置值
@Module org.koin.core.annotation 模块声明 分组定义
@ComponentScan org.koin.core.annotation 包扫描 自动发现定义
@Configuration org.koin.core.annotation 模块配置 构建变体/环境
@KoinApplication org.koin.core.annotation 应用入口点 引导Koin
@Monitor org.koin.core.annotation 性能监控 生产环境监控
文档版本:1.0 最后更新:2025-10-20 Koin注解版本:2.2.x+
org.koin.core.annotation模式2:示例
@Singleclass MyClass(val d : MyDependency)模式3:示例
@Factoryclass MyClass(val d : MyDependency)模式4:示例
@Scope(MyScope::class)@Scopedclass MyClass(val d : MyDependency)模式5:示例
@ViewModelScopeclass MyClass(val d : MyDependency)模式6:为什么选择Koin?
Koin为任何Kotlin应用(多平台、Android、后端等)提供简单高效的依赖注入集成方式。
Koin的目标:
- 通过智能API简化依赖注入基础设施
- 易于阅读和使用的Kotlin DSL,支持开发各类应用
- 提供从Android生态到Ktor后端等多种场景的集成方案
- 支持注解使用
Koin简介
让Kotlin开发更简单高效
Koin是一款智能Kotlin依赖注入库,让你专注于应用本身而非工具。
class MyRepository()
class MyPresenter(val repository : MyRepository) // 只需声明
val myModule = module { singleOf(::MyPresenter) singleOf(::MyRepository)}
Koin提供简单的工具和API,让你轻松构建和组装Kotlin相关技术栈,实现业务的高效扩展。
fun main() { // 只需启动Koin
startKoin { modules(myModule) }
}
为Android而生
借助Kotlin语言,Koin扩展了Android平台,提供原生平台之外的新功能。
class MyApplication : Application() { override fun onCreate() { super.onCreate() startKoin { modules(myModule) } } }
Koin提供简单强大的API,让你在Android组件的任何位置获取依赖,只需使用by inject()或by viewModel()
class MyActivity : AppCompatActivity() { val myPresenter : MyPresenter by inject()}
赋能Kotlin多平台
在移动平台间共享代码是Kotlin Multiplatform的主要应用场景之一。通过Kotlin Multiplatform Mobile,你可以构建跨平台移动应用,并在Android和iOS间共享通用代码。
Koin提供多平台依赖注入支持,帮助你在原生移动应用、Web/后端应用中构建组件。
性能与生产力
Koin是纯Kotlin框架,设计注重易用性和执行效率。它易于使用,不会影响编译时间,也无需额外插件配置。
Koin:依赖注入框架
Koin是一款流行的Kotlin依赖注入(DI)框架,提供现代轻量级的解决方案,以最少的样板代码管理应用依赖。
依赖注入 vs 服务定位器
虽然Koin看起来与服务定位器模式类似,但存在关键差异:
服务定位器:本质是可用服务的注册表,你可根据需要请求服务实例。它负责创建和管理这些实例,通常使用静态全局注册表。
依赖注入:相比之下,Koin是纯依赖注入框架。使用Koin时,你在模块中声明依赖,Koin负责对象的创建和连接。它支持创建多个独立模块,每个模块有自己的作用域,让依赖管理更模块化,避免潜在冲突。
Koin的理念:灵活性与最佳实践的融合
Koin同时支持DI和服务定位器模式,为开发者提供灵活性。但它强烈鼓励使用DI,尤其是构造函数注入,即依赖作为构造函数参数传递。这种方式提升了可测试性,让代码更易理解。
Koin的设计哲学以简单和易配置为核心,同时在必要时支持复杂配置。通过使用Koin,开发者可以有效管理依赖,DI是大多数场景下推荐和首选的方式。
透明性与设计概述
Koin是一款通用的控制反转(IoC)容器,支持依赖注入(DI)和服务定位器(SL)模式。为了让你清晰理解Koin的工作原理并有效使用它,我们来探讨以下方面:
Koin如何平衡DI和SL
Koin结合了DI和SL的元素,这会影响你使用框架的方式:
全局上下文使用:默认情况下,Koin提供一个全局可访问的组件,类似服务定位器。你可以使用KoinComponent或inject函数从中央注册表获取依赖。
隔离组件:尽管Koin鼓励使用依赖注入,尤其是构造函数注入,但它也支持隔离组件。这种灵活性意味着你可以在最适合的场景使用DI,同时在特定场景利用SL的优势。
Android组件中的SL:在Android开发中,Koin通常在Application和Activity等组件内部使用SL以简化配置。从这一点出发,Koin推荐使用DI,尤其是构造函数注入,以更结构化的方式管理依赖。但这并非强制要求,开发者可根据需要使用SL。
这对你的重要性
理解DI和SL的区别有助于有效管理应用依赖:
依赖注入:Koin鼓励使用DI,因为它提升了可测试性和可维护性。构造函数注入是首选方式,因为它让依赖更明确,提升代码清晰度。
服务定位器:虽然Koin支持SL以提供便利(尤其是在Android组件中),但仅依赖SL会导致耦合更紧密,可测试性降低。Koin的设计提供了平衡的方式,允许在实用场景使用SL,但将DI作为最佳实践推广。
充分利用Koin
要有效使用Koin:
遵循最佳实践:尽可能使用构造函数注入,以符合依赖管理的最佳实践。这种方式提升了可测试性和可维护性。
利用Koin的灵活性:在简化配置的场景使用SL,但尽量依赖DI管理核心应用依赖。
参考文档和示例:查看Koin的文档和示例,了解如何根据项目需求正确配置和使用DI与SL。
可视化依赖管理:图表和示例可帮助你理解Koin如何解析依赖并在不同上下文中管理它们。这些可视化工具能让你更清晰地理解Koin的内部工作原理。
通过提供这些指导,我们旨在帮助你有效驾驭Koin的特性和设计选择,确保你能充分发挥其潜力,同时遵循依赖管理的最佳实践。
class MyRepository()class MyPresenter(val repository : MyRepository) // just declare it val myModule = module { singleOf(::MyPresenter) singleOf(::MyRepository)}模式7:全局上下文使用:默认情况下,Koin提供一个全局可访问的组件,类似服务定位器。你可以使用KoinComponent或inject函数从中央注册表获取依赖。
KoinComponent模式8:定义
通过Koin,你可以在模块中描述定义。在本节中,我们将了解如何声明、组织和链接模块。
编写模块
Koin模块是声明所有组件的空间,使用module函数声明Koin模块:
val myModule = module { // 你的依赖定义 }
在该模块中,你可以按以下方式声明组件。
定义单例
声明单例组件意味着Koin容器会保留你声明的组件的唯一实例,使用module中的single函数声明单例:
class MyService()
val myModule = module { // 为MyService类声明单例实例 single { MyService() }}
在lambda中定义组件
single、factory和scoped关键字帮助你通过lambda表达式声明组件,该lambda描述构建组件的方式。通常我们通过构造函数实例化组件,但也可以使用任何表达式。
single { Class constructor // Kotlin表达式 }
lambda的返回类型是组件的主要类型
定义工厂
工厂组件声明是每次请求该定义时都会提供新实例的定义(Koin容器不会保留该实例,因为之后不会将该实例注入其他定义)。使用factory函数和lambda表达式构建组件。
class Controller()
val myModule = module { // 为Controller类声明工厂实例 factory { Controller() }}
提示:Koin容器不会保留工厂实例,因为每次请求定义时都会生成新实例。
解析与注入依赖
现在我们可以声明组件定义了,接下来要通过依赖注入链接实例。要在Koin模块中解析实例,只需使用get()函数请求所需的组件实例。该get()函数通常用于构造函数中,以注入构造函数值。
提示:要使用Koin容器进行依赖注入,我们必须采用构造函数注入的方式:在类构造函数中解析依赖。这样,你的实例会使用Koin注入的实例创建。
让我们看一个包含多个类的示例:
// Presenter <- Service
class Service()
class Controller(val view : View)
val myModule = module { // 将Service声明为单例实例 single { Service() } // 将Controller声明为单例实例,使用get()解析View实例 single { Controller(get()) }}
定义:绑定接口
single或factory定义使用其lambda定义的类型,即:single { T }
定义的匹配类型是该表达式的唯一匹配类型。
让我们看一个类和实现接口的示例:
// Service接口
interface Service{ fun doSomething()}
// Service实现
class ServiceImp() : Service { fun doSomething() { ... }}
在Koin模块中,我们可以使用Kotlin的as转换操作符:
val myModule = module { // 仅匹配ServiceImp类型 single { ServiceImp() } // 仅匹配Service类型 single { ServiceImp() as Service }}
你也可以使用推断类型表达式:
val myModule = module { // 仅匹配ServiceImp类型 single { ServiceImp() } // 仅匹配Service类型 single<Service> { ServiceImp() }}
注意:第二种声明方式更推荐,本文档后续将使用该方式。
额外类型绑定
在某些情况下,我们希望从一个定义匹配多个类型。
让我们看一个类和接口的示例:
// Service接口
interface Service{ fun doSomething()}
// Service实现
class ServiceImp() : Service{ fun doSomething() { ... }}
要让定义绑定额外类型,我们使用bind操作符和类:
val myModule = module { // 匹配ServiceImp和Service类型 single { ServiceImp() } bind Service::class}
注意:这里我们可以直接使用get()解析Service类型。但如果有多个定义绑定Service,我们必须使用bind<>()函数。
定义:命名与默认绑定
你可以为定义指定名称,以帮助区分同一类型的两个定义:
只需通过名称请求定义:
val myModule = module { single<Service>(named("default")) { ServiceImpl() } single<Service>(named("test")) { ServiceImpl() }}
val service : Service by inject(qualifier = named("default"))
get()和by inject()函数允许你根据需要指定定义名称,该名称是由named()函数生成的限定符。
默认情况下,Koin会根据类型或名称绑定定义(如果类型已绑定到某个定义)。
val myModule = module { single<Service> { ServiceImpl1() } single<Service>(named("test")) { ServiceImpl2() }}
然后:
val service : Service by inject() 会触发ServiceImpl1定义
val service : Service by inject(named("test")) 会触发ServiceImpl2定义
声明注入参数
在任何定义中,你都可以使用注入参数:即会被注入并供定义使用的参数:
class Presenter(val view : View)
val myModule = module { single{ (view : View) -> Presenter(view) }}
与已解析依赖(使用get()解析)不同,注入参数是通过解析API传递的参数。这意味着这些参数是通过get()和by inject()配合parametersOf函数传递的值:
val presenter : Presenter by inject { parametersOf(view) }
更多内容请查看注入参数章节
定义终止 - OnClose
你可以使用onClose函数,为定义添加关闭时的回调:
class Presenter(val view : View)
val myModule = module { factory { (view : View) -> Presenter(view) } onClose { // 关闭回调 - 此处为Presenter }}
使用定义标志
Koin DSL还提供了一些标志。
启动时创建实例
定义或模块可标记为CreatedAtStart,以在启动时(或你指定的时间)创建。首先在模块或定义上设置createdAtStart标志。
定义上的CreatedAtStart标志
val myModuleA = module { single<Service> { ServiceImp() }}
val myModuleB = module { // 该定义预创建 single<Service>(createdAtStart=true) { TestServiceImp() }}
模块上的CreatedAtStart标志:
val myModuleA = module { single<Service> { ServiceImp() }}
val myModuleB = module(createdAtStart=true) { single<Service>{ TestServiceImp() }}
startKoin函数会自动创建标记为createdAtStart的定义实例。
// 启动Koin模块
startKoin { modules(myModuleA,myModuleB)}
提示:如果你需要在特定时间加载某些定义(例如在后台线程而非UI线程),只需get/inject所需组件即可。
按定义显式覆盖(4.2.0+)
当你启用allowOverride(false)以进行严格控制,但需要特定定义覆盖现有定义时,可以使用.override()选项:
val productionModule = module { single<Service> { ProductionService() }}
val testModule = module { // 显式标记该定义允许覆盖 single<Service> { MockService() }.override()}
startKoin { allowOverride(false) // 严格模式 modules(productionModule, testModule)}
你也可以配合withOptions使用:
single<Service> { MockService() } withOptions { override()}
这在以下场景中特别有用:
- 需要覆盖生产服务的测试配置
- 有条件覆盖实现的功能标志
- 特定插件可覆盖默认值的插件系统
更多详情请查看模块 - 显式覆盖
处理泛型
Koin定义不考虑泛型类型参数。例如,以下模块尝试定义两个List定义:
module { single { ArrayList<Int>() } single { ArrayList<String>() }}
Koin无法启动这样的模块,因为它会认为你要覆盖其中一个定义。
要允许使用这两个定义,你必须通过名称或位置(模块)区分它们。例如:
module { single(named("Ints")) { ArrayList<Int>() } single(named("Strings")) { ArrayList<String>() }}
moduleExample Code Patterns
示例代码模式
Example 1 (kotlin):
kotlin
@Singleclass MyClass(val d : MyDependency)Example 2 (kotlin):
kotlin
single { MyClass(get()) }Example 3 (kotlin):
kotlin
// Tag your component to declare a definition@Singleclass MyComponentExample 4 (kotlin):
kotlin
// Declare a module and scan for annotations@Moduleclass MyModuleExample 5 (groovy):
groovy
dependencies { // Koin for Android implementation("io.insert-koin:koin-android:$koin_version")}示例1(kotlin):
kotlin
@Singleclass MyClass(val d : MyDependency)示例2(kotlin):
kotlin
single { MyClass(get()) }示例3(kotlin):
kotlin
// 标记组件以声明定义
@Singleclass MyComponent示例4(kotlin):
kotlin
// 声明模块并扫描注解
@Moduleclass MyModule示例5(groovy):
groovy
dependencies { // Koin for Android implementation("io.insert-koin:koin-android:$koin_version")}Reference Files
参考文件
This skill includes comprehensive documentation in :
references/- getting_started.md - Getting Started documentation
Use to read specific reference files when detailed information is needed.
view本技能在目录中包含全面的文档:
references/- getting_started.md - 入门文档
当需要详细信息时,使用命令查看特定参考文件。
viewWorking with This Skill
使用本技能
For Beginners
面向初学者
Start with the getting_started or tutorials reference files for foundational concepts.
从入门文档或教程参考文件开始,了解基础概念。
For Specific Features
面向特定功能
Use the appropriate category reference file (api, guides, etc.) for detailed information.
使用相应类别的参考文件(如api、指南等)获取详细信息。
For Code Examples
面向代码示例
The quick reference section above contains common patterns extracted from the official docs.
上方的快速参考部分包含从官方文档中提取的常见模式。
Resources
资源
references/
references/
Organized documentation extracted from official sources. These files contain:
- Detailed explanations
- Code examples with language annotations
- Links to original documentation
- Table of contents for quick navigation
从官方来源提取的结构化文档,包含:
- 详细说明
- 带语言注解的代码示例
- 指向原始文档的链接
- 用于快速导航的目录
scripts/
scripts/
Add helper scripts here for common automation tasks.
在此添加用于常见自动化任务的辅助脚本。
assets/
assets/
Add templates, boilerplate, or example projects here.
在此添加模板、样板代码或示例项目。
Notes
说明
- This skill was automatically generated from official documentation
- Reference files preserve the structure and examples from source docs
- Code examples include language detection for better syntax highlighting
- Quick reference patterns are extracted from common usage examples in the docs
- 本技能由官方文档自动生成
- 参考文件保留了源文档的结构和示例
- 代码示例包含语言检测,以实现更好的语法高亮
- 快速参考模式提取自文档中的常见使用示例
Updating
更新
To refresh this skill with updated documentation:
- Re-run the scraper with the same configuration
- The skill will be rebuilt with the latest information
要使用更新后的文档刷新本技能:
- 使用相同配置重新运行抓取工具
- 技能将使用最新信息重建