Kotlin is Google's preferred language for Android development. It reduces boilerplate compared to Java, eliminates most null pointer exceptions at compile time, and works seamlessly with existing Java code and Android APIs.
Kotlin — Syntax basics// Single-line comment
/* Multi-line
comment */
val name = "Nikhil"
val greeting = "Hello, $name!" // string template
val details = "User: ${name.uppercase()}" // expression in template
val multiline = """
Line 1
Line 2
""".trimIndent()
Control flow
Kotlin — if, when, loops// if as expression
val status = if (score >= 50) "Pass" else "Fail"
// when — powerful switch replacement
val label = when (networkType) {
"WIFI" -> "Connected via Wi-Fi"
"MOBILE" -> "Connected via Mobile Data"
else -> "No connection"
}
// for loop
for (i in 1..5) println(i)
for (item in items) println(item)
// while loop
while (retryCount < 3) {
retryCount++
}
Kotlin vs Java syntax
Java
Kotlin
String name = "Nikhil";
val name = "Nikhil"
if-else blocks
if-else as expression
switch (x) { ... }
when (x) { ... }
System.out.println()
println()
new ArrayList<>()
mutableListOf()
2Variables
Kotlin uses val for read-only values and var for mutable variables. Prefer val by default — immutability makes code safer and easier to reason about.
val vs var
Kotlin — Variable declarationsval appName = "LearnHub" // read-only, cannot reassign
var loginCount = 0 // mutable, can reassign
loginCount = 1
// Explicit types (optional when inferred)
val maxRetries: Int = 3
var userName: String = "Guest"
Basic types
Type
Example
Android Use
Int
42
IDs, counts, resource IDs
Long
1_000_000L
Timestamps
Double / Float
3.14
Coordinates, ratings
Boolean
true
Feature flags, toggles
String
"Hello"
UI text, API fields
Char
'A'
Single characters
Type conversion
Kotlin — Safe type conversionval countStr = "42"
val count = countStr.toInt() // String → Int
val price = 99.99
val priceInt = price.toInt() // truncates to 99
// Android example — parse EditText input
val ageText = binding.etAge.text.toString()
val age = ageText.toIntOrNull() ?: 0 // safe parse with default
Constants
Kotlin — Companion object constantsclass ApiConfig {
companion object {
const val BASE_URL = "https://api.example.com/"
const val TIMEOUT_SECONDS = 30
}
}
// Top-level constant
const val APP_TAG = "LearnHub"
3Functions
Kotlin functions are declared with fun. They support default parameters, named arguments, single-expression bodies, and higher-order functions — reducing boilerplate throughout Android code.
Basic and single-expression functions
Kotlin — Function syntaxfun greet(name: String): String {
return "Hello, $name!"
}
// Single-expression — return type inferred
fun add(a: Int, b: Int) = a + b
fun isNetworkAvailable(context: Context): Boolean {
// implementation...
return true
}
Kotlin — Lambdas// Lambda as parameter
fun fetchData(onSuccess: (String) -> Unit, onError: (Exception) -> Unit) {
try {
onSuccess("Data loaded")
} catch (e: Exception) {
onError(e)
}
}
// Usage — trailing lambda syntax
fetchData(
onSuccess = { data -> println(data) },
onError = { e -> println(e.message) }
)
// Shorthand when lambda is last parameter
button.setOnClickListener { viewModel.onButtonClick() }
4Classes
Kotlin classes are concise. Primary constructors, data classes, objects, and sealed classes cover most Android patterns — from API models to UI state and singletons.
Class with primary constructor
Kotlin — User classclass User(
val id: Int,
var name: String,
val email: String
) {
fun displayName(): String = name.uppercase()
override fun toString(): String = "User(id=$id, name=$name)"
}
Data class — API models
Kotlin — Post data classdata class Post(
val id: Int,
val title: String,
val body: String,
val userId: Int = 0
)
// Auto-generated: equals(), hashCode(), toString(), copy()
val post = Post(1, "Hello", "World")
val updated = post.copy(title = "Updated Title")
Inheritance and interfaces
Kotlin — open class and overrideopen class Animal(val name: String) {
open fun speak(): String = "..."
}
class Dog(name: String) : Animal(name) {
override fun speak(): String = "Woof!"
}
interface ClickListener {
fun onClick()
fun onLongClick(): Boolean = false // default implementation
}
class MyButton : ClickListener {
override fun onClick() { /* handle click */ }
}
Object and companion object
Kotlin — Singleton and factory// Singleton
object NetworkManager {
fun isConnected(context: Context): Boolean { /* ... */ return true }
}
// Companion object — static-like members
class TaskRepository private constructor() {
companion object {
@Volatile
private var instance: TaskRepository? = null
fun getInstance(): TaskRepository {
return instance ?: synchronized(this) {
instance ?: TaskRepository().also { instance = it }
}
}
}
}
Sealed class — UI state
Kotlin — Sealed class for statesealed class UiState {
object Loading : UiState()
data class Success(val data: List<Task>) : UiState()
data class Error(val message: String) : UiState()
}
// Exhaustive when — compiler ensures all cases handled
fun render(state: UiState) = when (state) {
is UiState.Loading -> showProgressBar()
is UiState.Success -> showList(state.data)
is UiState.Error -> showError(state.message)
}
5Null Safety
Kotlin's type system distinguishes nullable and non-nullable types at compile time. This eliminates most NullPointerException crashes — the number one cause of Android app failures.
Nullable vs non-nullable types
Kotlin — Null typesvar name: String = "Nikhil" // cannot be null
var nickname: String? = null // can be null
// name = null // COMPILE ERROR
nickname = null // OK
Safe call and Elvis operator
Kotlin — ?. and ?: operatorsval length = nickname?.length // returns null if nickname is null
val display = nickname ?: "Anonymous" // Elvis — default if null
val count = nickname?.length ?: 0
// Android example
val email = intent.getStringExtra("email") ?: ""
binding.tvEmail.text = user?.email?.uppercase() ?: "No email"
let, also, apply, run, with
Kotlin — Scope functions// let — execute block if not null
user?.let { u ->
binding.tvName.text = u.name
binding.tvEmail.text = u.email
}
// apply — configure object, return object
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra("id", taskId)
putExtra("title", title)
}
// also — side effect, return object
val result = fetchData().also { Log.d("API", "Got ${it.size} items") }
Safe casts and not-null assertion
Kotlin — as? and !!// Safe cast — returns null if wrong type
val fragment = supportFragmentManager.findFragmentById(R.id.container) as? MyFragment
// Not-null assertion — use only when 100% sure (avoid !! in production)
val name = nickname!! // throws NPE if null
// Prefer explicit check
if (nickname != null) {
println(nickname.length) // smart cast — Kotlin knows it's not null
}
6Collections
Kotlin provides rich collection types — List, Set, Map — with read-only and mutable variants, plus powerful functional operations for filtering, mapping, and sorting API data.
Creating collections
Kotlin — List, Set, Map// Read-only (immutable interface)
val fruits = listOf("Apple", "Banana", "Mango")
val uniqueIds = setOf(1, 2, 3)
val userMap = mapOf("name" to "Nikhil", "role" to "Developer")
// Mutable
val tasks = mutableListOf<Task>()
tasks.add(Task(1, "Learn Kotlin"))
tasks.removeAt(0)
val scores = mutableMapOf<String, Int>()
scores["Alice"] = 95
scores["Bob"] = 87
Functional operations
Kotlin — map, filter, sortedBydata class Task(val id: Int, val title: String, val completed: Boolean)
val tasks = listOf(
Task(1, "Learn Kotlin", true),
Task(2, "Build App", false),
Task(3, "Publish", false)
)
val pendingTitles = tasks
.filter { !it.completed }
.sortedBy { it.title }
.map { it.title }
val completedCount = tasks.count { it.completed }
val firstPending = tasks.firstOrNull { !it.completed }
Collections in Android
Kotlin — RecyclerView adapter dataclass TaskAdapter : RecyclerView.Adapter<TaskViewHolder>() {
private val items = mutableListOf<Task>()
fun submitList(newTasks: List<Task>) {
items.clear()
items.addAll(newTasks)
notifyDataSetChanged()
}
override fun getItemCount() = items.size
override fun onBindViewHolder(holder: TaskViewHolder, position: Int) {
holder.bind(items[position])
}
}
Collection types summary
Read-only
Mutable
Factory Function
List<T>
MutableList<T>
listOf() / mutableListOf()
Set<T>
MutableSet<T>
setOf() / mutableSetOf()
Map<K,V>
MutableMap<K,V>
mapOf() / mutableMapOf()
7Kotlin for Android
Kotlin integrates deeply with Android APIs and Jetpack libraries. These patterns appear in nearly every modern Android project — from Activities and Fragments to ViewModels, coroutines, and Compose.
Activity with View Binding
Kotlin — MainActivity.ktclass MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btnSubmit.setOnClickListener {
val name = binding.etName.text.toString().trim()
if (name.isNotEmpty()) {
viewModel.saveUser(name)
} else {
binding.etName.error = "Name required"
}
}
}
}
ViewModel with coroutines
Kotlin — ViewModel + coroutinesclass UserViewModel(
private val repository: UserRepository = UserRepository()
) : ViewModel() {
private val _users = MutableLiveData<List<User>>()
val users: LiveData<List<User>> = _users
fun loadUsers() {
viewModelScope.launch {
try {
_users.value = repository.fetchUsers()
} catch (e: Exception) {
Log.e("UserVM", "Failed to load", e)
}
}
}
}
Intent extras with Kotlin
Kotlin — Intent helpers// Start Activity with extras
fun Context.openDetail(taskId: Int, title: String) {
startActivity(Intent(this, DetailActivity::class.java).apply {
putExtra("task_id", taskId)
putExtra("title", title)
})
}
// Receive in DetailActivity
class DetailActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val taskId = intent.getIntExtra("task_id", -1)
val title = intent.getStringExtra("title") ?: ""
}
}
Property delegates
Kotlin — by viewModels(), by lazyclass TaskFragment : Fragment() {
private val viewModel: TaskViewModel by viewModels()
private val adapter by lazy { TaskAdapter() }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.recyclerView.adapter = adapter
viewModel.tasks.observe(viewLifecycleOwner) { tasks ->
adapter.submitList(tasks)
}
}
}
Common Android Kotlin patterns
Pattern
Kotlin Feature
Example
API model
data class
data class User(val id: Int, val name: String)
UI state
sealed class
sealed class UiState { ... }
Click listener
Lambda
button.setOnClickListener { ... }
ViewModel access
Delegate
by viewModels()
Async work
Coroutines
viewModelScope.launch { ... }
Null-safe UI
?. / ?:
user?.name ?: "Guest"
8Hands-On Exercises
1
Write a Kotlin program using syntax basics — variables, when, loops, and string templates.
2
Declare variables with val and var. Parse user input from an EditText safely with toIntOrNull().
3
Create functions with default parameters and an extension function View.visible() / View.gone().
4
Define a data class for a Task, a sealed class for UI state, and a singleton object for app config.
5
Practice null safety — use ?., ?:, and let to handle nullable API response fields.
6
Filter, map, and sort a list of tasks using collection operations. Display results in a RecyclerView.
7
Build a simple Android screen using Kotlin for Android — View Binding, by viewModels(), and LiveData observation.
Kotlin for Android MCQ Practice
10 Basic MCQs10 Advanced MCQs
10 Basic Kotlin for Android MCQs
1
val vs var?
AIdentical
Bval immutable reference; var mutable
Cvar read-only
Dval mutable
Explanation: val cannot reassign; object may still be mutable.
2
Null safety — String? means?
AEmpty string
BNon-null always
CNullable String type
DDeprecated
Explanation: Must check before use or use safe calls ?.
3
data class provides?
AGPS
BSQL mapping only
CLayout inflation
Dequals, hashCode, toString, copy automatically
Explanation: Ideal for model/DTO classes.
4
fun keyword defines?
AFunction
BVariable
CClass only
DInterface only
Explanation: Functions are first-class in Kotlin.
5
Safe call operator?
A!! force unwrap safe
B?. calls only if not null
CCreates thread
DSQL query
Explanation: user?.name returns null if user is null.
6
when expression?
AImport statement
BLoop only
CEnhanced switch matching values/types
DGradle task
Explanation: when (x) { is String -> ... else -> ... }
7
lateinit used for?
ASQL
BNullable fields
CConstants
DNon-null var initialized later
Explanation: lateinit var binding: ActivityMainBinding — must assign before use.
8
Object keyword creates?
ASingleton or anonymous object
BArray only
CXML layout
DManifest
Explanation: object Repository { } is singleton.
9
Extension function?
AOverride private method
BAdd function to existing class without inheritance
CJava only
DDeprecated
Explanation: fun String.capitalizeWords(): String { ... }
10
Google recommends Kotlin because?
ANo Java interop
BReplaces Linux
CConcise, null-safe, official Android language
DSmaller APK always
Explanation: Kotlin is preferred for new Android projects since 2019.
10 Advanced Kotlin for Android MCQs
11
Sealed class?
AOpen to all subclasses globally
BRestricted class hierarchy — exhaustive when
CSQL table
DService type
Explanation: sealed class Result { object Loading; data class Success(val data: T) }
12
Inline function?
AJava incompatible
BAlways slower
CCopies bytecode at call site — reduces lambda overhead
DDeprecated
Explanation: inline fun with higher-order functions like let scope.
13
Coroutines launch vs async?
Alaunch SQL only
BSame
Casync UI only
Dlaunch: fire-and-forget Job; async: returns Deferred result
Explanation: async { compute() }.await() for parallel results.
14
Companion object?
AStatic-like members on class
BMultiple per class
CReplaces constructor
DManifest entry
Explanation: Companion object Factory { fun create() }
15
Delegation by?
AInheritance only
BImplements interface forwarding to delegate instance
CGPS
DRoom
Explanation: class RepoImpl(r: Remote) : Repo by r
16
Reified type parameter?
AJava feature
BAll generics reified
CAccess generic type at runtime with inline
DSQL only
Explanation: inline fun Gson.fromJson() used with inline.
17
Scope functions let/apply/run?
ALayout only
BAll identical
CDeprecated
Dlet: it lambda result; apply: this configure; run: block result
Explanation: apply returns receiver; let passes as it.