Skip to main content
Version: 4.2

Starting Koin on Android

This page shows how to start Koin in an Android app: the Application class, the Android Context, the Logcat logger, properties from assets, module loading after start, and AndroidX App Startup. It assumes the io.insert-koin:koin-android dependency is in your build (see Gradle Setup). For what startKoin does on every platform, see Starting Koin.

Start Koin in your Application class​

Start Koin once, in Application.onCreate():

import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.core.context.startKoin

class MainApplication : Application() {

override fun onCreate() {
super.onCreate()

startKoin {
androidLogger()
androidContext(this@MainApplication)
modules(appModule)
}
}
}

appModule is a module { } declared with the Compiler Plugin DSL (single<UserRepository>(), viewModel<UserViewModel>()).

Register the class in AndroidManifest.xml with android:name=".MainApplication" on the <application> tag, or Android never runs it.

androidContext() adds the Application instance to Koin, bound to both Application and Context. Call it before any option that needs a Context, such as androidFileProperties() or workManagerFactory().

Android Context in definitions​

A class that needs a Context declares it in its constructor. No qualifier is needed: Koin resolves Context to the instance passed to androidContext().

class PreferencesStore(private val context: Context)
class NotificationHelper(private val application: Application)

val androidModule = module {
single<PreferencesStore>()
single<NotificationHelper>()
}
FunctionReturnsFails when
androidContext()The closest Context: the Application, or the Activity in an Activity scopeNo androidContext() was given at start (MissingAndroidContextException)
androidApplication()Always the Application instanceNo Application was given to androidContext()

Both functions are shortcuts for get<Context>() and get<Application>(), from org.koin.android.ext.koin.

Which Context you get​

In a single, or any definition resolved from the root scope, Context is the Application. This is safe for objects that live as long as the app.

In a definition resolved from an Activity scope, Context resolves to the Activity first, because the Activity is the source of that scope. This is how a scoped presenter can get the Activity. See Android Scopes.

Activity context​

Don't declare an Activity as a dependency of a single: the singleton keeps the Activity alive after it is destroyed, and the Activity leaks. When a class needs the Activity (screen metrics, a dialog), create it in the Activity, pass the Activity as an injected parameter, or declare it in an Activity scope:

class ScreenMetrics(private val activity: Activity) {
fun screenWidth(): Int = activity.resources.displayMetrics.widthPixels
}

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val metrics = ScreenMetrics(this)
}
}

Several instances of the same Android type​

When two definitions share a type, such as two SharedPreferences files, tell them apart with a qualifier:

val preferencesModule = module {
single(named("settings")) {
androidContext().getSharedPreferences("settings", Context.MODE_PRIVATE)
}
single(named("session")) {
androidContext().getSharedPreferences("session", Context.MODE_PRIVATE)
}
}

Logging​

androidLogger() sends Koin logs to Logcat. The default level is Level.INFO:

startKoin {
androidLogger(Level.DEBUG)
androidContext(this@MainApplication)
modules(appModule)
}

Level.DEBUG logs every resolution and its duration, which helps when you debug a missing definition. It also slows resolution down, so keep it for debug builds: androidLogger(if (BuildConfig.DEBUG) Level.DEBUG else Level.ERROR). Other loggers are listed in Starting Koin.

Properties from assets​

androidFileProperties() loads Koin properties from a file in src/main/assets. The default file name is koin.properties:

startKoin {
androidContext(this@MainApplication)
androidFileProperties() // assets/koin.properties
// androidFileProperties("app.properties")
modules(appModule)
}

It reads the file through the Context, so call it after androidContext(). If the file is missing, Koin logs it and continues. To read a property in a definition, see Starting Koin.

Loading modules after start​

loadKoinModules() and unloadKoinModules() add or remove modules while the app runs. On Android, this fits a feature that is only used from a few screens:

private val premiumModules = lazy { loadKoinModules(premiumModule) }

class PremiumActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
premiumModules.value
super.onCreate(savedInstanceState)
}
}
  • Load before super.onCreate(): Fragments restored by the system then find their dependencies.
  • Load once per process: loading the same module again re-registers its definitions, logs an override warning, and fails if Koin runs with allowOverride(false).
  • Unload with care: unloadKoinModules(premiumModule) drops the module definitions and their instances. Unload only when the feature is no longer needed, never on a configuration change, and track the loaded state yourself if you load it again later.

Lazy modules​

On large apps, loading every module in Application.onCreate() adds to startup time on the main thread. lazyModules() loads the modules you mark with lazyModule { } on a background thread, while the modules needed for the first screen load with modules(). Setup, waiting for completion and limits are in Lazy Modules.

Start with AndroidX App Startup​

AndroidX App Startup runs initializers from one ContentProvider, before Application.onCreate(). The io.insert-koin:koin-androidx-startup artifact starts Koin as one of those initializers. Implement KoinStartup in your Application and return the configuration from onKoinStartup():

import org.koin.androix.startup.KoinStartup
import org.koin.dsl.koinConfiguration

@OptIn(KoinExperimentalAPI::class)
class MainApplication : Application(), KoinStartup {

override fun onKoinStartup() = koinConfiguration {
androidContext(this@MainApplication)
modules(appModule)
}
}

KoinStartup replaces the startKoin call in onCreate(): don't call both. The package name is org.koin.androix.startup (with this spelling), and the API is marked @KoinExperimentalAPI.

If another initializer needs Koin, make it depend on KoinInitializer. App Startup creates initializers itself, so an initializer is an entry point: it implements KoinComponent to retrieve its dependencies.

class CrashTrackerInitializer : Initializer<Unit>, KoinComponent {

private val crashTracker: CrashTracker by inject()

override fun create(context: Context) {
crashTracker.configure(context)
}

override fun dependencies(): List<Class<out Initializer<*>>> =
listOf(KoinInitializer::class.java)
}
warning

KoinStartup still runs on the main thread, during app startup. It does not make Koin start faster. Use it only to order Koin with other App Startup initializers. To move module loading off the main thread, use Lazy Modules.

Starting Koin outside the Application class​

You can call startKoin from another class, as long as it runs once per process and before the first injection. Pass the application context, not an Activity:

startKoin {
androidContext(context.applicationContext)
modules(appModule)
}

startKoin registers a global instance. A library or SDK that ships its own Koin setup should not use it, because it would conflict with the host app: use an isolated context instead (see Context Isolation).