Injecting in Android
Once you have declared some modules and started Koin, how can you retrieve your instances in your Android Activity, Fragments, or Services?
Ready for Android Classes
Activity, Fragment & Service are extended with Koin extensions. Any ComponentCallbacks class has access to:
by inject()- lazy evaluated instance from Koin containerget()- eager fetch instance from Koin containerby viewModel()- lazy ViewModel instancegetViewModel()- eager ViewModel instance
Defining Dependencies
Compiler Plugin DSL
val appModule = module {
factory<Presenter>()
viewModel<UserViewModel>()
}
Annotations
@Factory
class Presenter(private val repository: UserRepository)
@KoinViewModel
class UserViewModel(private val repository: UserRepository) : ViewModel()
Classic DSL
val appModule = module {
factory { Presenter(get()) }
viewModel { UserViewModel(get()) }
}
Injecting in Activity
class DetailActivity : AppCompatActivity() {
// Lazy inject Presenter
private val presenter: Presenter by inject()
// Lazy inject ViewModel
private val viewModel: UserViewModel by viewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Use presenter and viewModel
}
}
Injecting in Fragment
class UserFragment : Fragment() {
// Fragment's own ViewModel
private val viewModel: UserViewModel by viewModel()
// Shared ViewModel with Activity
private val sharedViewModel: SharedViewModel by activityViewModel()
// Regular dependency
private val presenter: Presenter by inject()
}
Injecting in Service
class MyService : Service() {
private val repository: UserRepository by inject()
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
repository.doSomething()
return START_STICKY
}
}
Eager vs Lazy Injection
class DetailActivity : AppCompatActivity() {
// Lazy - created on first access
private val presenter: Presenter by inject()
// Eager - created immediately
private val service: MyService = get()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Or get eagerly in a function
val anotherPresenter: Presenter = get()
}
}
| Method | When Created | Use Case |
|---|---|---|
by inject() | On first access | Most cases, avoids unnecessary creation |
get() | Immediately | When you need the instance right away |
If your class doesn't have Koin extensions, implement the KoinComponent interface to access inject() or get().
Injection with Parameters
Pass parameters at injection time:
@Factory
class UserPresenter(
@InjectedParam val userId: String,
val repository: UserRepository
)
class UserActivity : AppCompatActivity() {
private val presenter: UserPresenter by inject { parametersOf("user_123") }
}
Injection with Qualifiers
When you have multiple definitions of the same type:
val appModule = module {
single<Database>(named("local")) { LocalDatabase() }
single<Database>(named("remote")) { RemoteDatabase() }
}
class MyActivity : AppCompatActivity() {
private val localDb: Database by inject(named("local"))
private val remoteDb: Database by inject(named("remote"))
}
Using Android Context in Definitions
Once your Application class configures Koin with androidContext, you can resolve it in your definitions.
Annotations
With annotations, simply declare a Context or Application parameter - it will be automatically injected:
@Factory
class MyPresenter(private val context: Context)
@Singleton
class MyRepository(private val application: Application)
DSL
Use androidContext() or androidApplication() functions in your module:
val appModule = module {
factory {
MyPresenter(androidContext())
}
single {
MyRepository(androidApplication())
}
}
Android Scope & Context Resolution
When you have a scope binding the Context type, you may need to resolve Context from different levels:
class MyPresenter(val context: Context)
val appModule = module {
scope<MyActivity> {
scoped { MyPresenter(get()) }
}
}
Context resolution:
get()- resolves closestContext, hereMyActivityandroidContext()- resolves closestContext, hereMyActivityandroidApplication()- resolvesApplicationfrom Koin setup