Kotlin for Android

This section documents Kotlin 2.4.x on the JVM, as published at kotlinlang.org, which is the reference these pages are written and verified against.

This content was generated with the assistance of AI and should be verified against kotlinlang.org before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

Building on Kotlin and the JVM — which established that Kotlin is a general-purpose JVM language and Android is one target among several — this page covers what Android specifically adds on top of the Kotlin language itself.

Google’s Preferred Android Language Since 2019

At Google I/O 2019, Google announced that Android app development would be Kotlin-first: new Jetpack APIs are designed Kotlin-first (often exposing Kotlin-only ergonomics such as coroutine support or DSL-style builders), official samples and documentation default to Kotlin, and Java remains fully supported but is no longer the primary language new guidance is written against. This did not change anything about Kotlin/JVM itself — the .kt files in an Android app compile through the exact same Kotlin/JVM pipeline described in Kotlin and the JVM — it changed which platform-specific libraries and tooling exist to make Kotlin code on Android pleasant to write.

Android KTX

KTX is a family of Kotlin extension libraries (core-ktx, fragment-ktx, activity-ktx, and more) that add idiomatic Kotlin extension functions and properties (Extension Functions and Scope Functions) over verbose Android framework APIs:

// without KTX
val bundle = Bundle()
bundle.putString("name", "Ada")

val editor = sharedPreferences.edit()
editor.putBoolean("dark_mode", true)
editor.apply()

// with core-ktx
val bundle = bundleOf("name" to "Ada")            // Pair-based builder, see Data Classes and Destructuring
sharedPreferences.edit { putBoolean("dark_mode", true) }   // "edit { }" auto-applies when the block completes

KTX changes nothing about what the underlying Android APIs do — it is a thin, additive layer, so any Java Android knowledge (the Activity/Fragment lifecycle, `Intent`s, `Bundle`s) transfers directly.

Jetpack Pointers

Jetpack is Android’s official library suite; three components come up constantly in Kotlin Android code and are worth a one-paragraph orientation each (a full treatment of any one is out of scope for this Kotlin-language section):

  • ViewModel — survives configuration changes (like a screen rotation) and is the conventional home for UI state exposed as a StateFlow (Flows) that a screen observes.

  • Room — a SQLite persistence library with compile-time-verified queries; its DAOs are commonly declared as suspend fun`s or as functions returning `Flow<T> directly, integrating persistence with coroutines with no manual thread-switching.

  • Jetpack Compose — Android’s modern, Kotlin-only declarative UI toolkit (not covered here in depth — Compose is a large enough topic for its own dedicated reference; this section only notes that it exists and is built entirely around Kotlin language features, particularly lambdas with receiver (Type-Safe Builders and DSLs) and coroutines).

class UserViewModel(private val repository: UserRepository) : ViewModel() {
    private val _uiState = MutableStateFlow(UiState.Loading)
    val uiState: StateFlow<UiState> = _uiState.asStateFlow()

    fun loadUser(id: Int) {
        viewModelScope.launch {                       // see "Coroutines on Android" below
            _uiState.value = UiState.Loaded(repository.findById(id))
        }
    }
}

Coroutines on Android: viewModelScope and lifecycleScope

Coroutines Basics introduced CoroutineScope as the mechanism that ties a coroutine’s lifetime to something meaningful; on Android, two ready-made scopes are provided so an app rarely needs to build its own:

Scope Tied to

viewModelScope

a ViewModel instance — automatically cancelled when the ViewModel is cleared (the screen is finished for good, not just rotated).

lifecycleScope

a LifecycleOwner (an Activity/Fragment) — automatically cancelled when that component is destroyed.

class UserFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        lifecycleScope.launch {
            viewModel.uiState.collect { state ->    // collecting a Flow, cancelled automatically on destroy
                render(state)
            }
        }
    }
}

Using these scopes instead of a manually-created CoroutineScope is what makes structured concurrency actually pay off on Android: a coroutine launched this way simply cannot outlive the screen that started it.

See Also

  • Kotlin and the JVM — Android as one Kotlin/JVM target among several.

  • Coroutines Basics and Flows — the coroutine/Flow foundation viewModelScope/StateFlow build on.

  • Build and Tooling — Android Studio and the Gradle Kotlin DSL, shared with non-Android Kotlin projects.