Kotlin
kotlin
Kotlin programming for Android, coroutines, and JVM development. Use for .kt files.
SKILL.md
Full skill instructions
Kotlin
Modern Kotlin development with coroutines, null safety, and idiomatic patterns.
When to Use
- Working with
.ktfiles - Android app development
- JVM backend with Spring Boot/Ktor
- Multiplatform projects (KMP)
Quick Start
data class User(
val id: String,
val name: String,
val email: String,
val createdAt: Instant = Clock.System.now()
)
suspend fun fetchUser(id: String): User? {
return apiService.getUser(id)
}
Core Concepts
Null Safety
// Nullable types
val name: String? = null
// Safe calls
val length = name?.length
// Elvis operator
val len = name?.length ?: 0
// Smart casts
if (name != null) {
println(name.length) // Smart cast to String
}
// Not-null assertion (use sparingly)
val len = name!!.length
Data Classes & Sealed Classes
data class User(
val id: String,
val name: String,
val email: String
)
sealed class Result<out T> {
data class Success<T>(val data: T) : Result<T>()
data class Error(val message: String) : Result<Nothing>()
object Loading : Result<Nothing>()
}
// Exhaustive when
fun handleResult(result: Result<User>) = when (result) {
is Result.Success -> println(result.data)
is Result.Error -> println(result.message)
Result.Loading -> println("Loading...")
}
Common Patterns
Coroutines
// Suspend function
suspend fun fetchData(): List<Item> {
return withContext(Dispatchers.IO) {
api.fetchItems()
}
}
// Parallel execution
suspend fun loadDashboard(): Dashboard {
return coroutineScope {
val user = async { fetchUser() }
val orders = async { fetchOrders() }
Dashboard(user.await(), orders.await())
}
}
// Flow for streams
fun observeUsers(): Flow<List<User>> = flow {
while (true) {
emit(fetchUsers())
delay(5000)
}
}.flowOn(Dispatchers.IO)
Extension Functions
fun String.isValidEmail(): Boolean {
return Regex("^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}\$").matches(this)
}
fun <T> List<T>.secondOrNull(): T? = getOrNull(1)
inline fun <T> Result<T>.onSuccess(action: (T) -> Unit): Result<T> {
if (this is Result.Success) action(data)
return this
}
Best Practices
Do:
- Use data classes for DTOs
- Prefer immutability (
valovervar) - Use sealed classes for state
- Use coroutines for async work
Don't:
- Use
!!without null check - Create utility classes (use extensions)
- Block main thread with
runBlocking - Ignore cancellation in coroutines
Troubleshooting
| Error | Cause | Solution |
|---|---|---|
NullPointerException | Force unwrap on null | Use safe call ?. |
CancellationException | Coroutine cancelled | Handle or propagate |
IllegalStateException | Invalid state access | Check state before access |
