kotlin-expert

Expert guidance for Kotlin development, Android, coroutines, Kotlin Multiplatform, and modern JVM development.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "kotlin-expert" with this command: npx skills add personamanagmentlayer/pcl/personamanagmentlayer-pcl-kotlin-expert

Kotlin Expert

Expert guidance for Kotlin development, Android, coroutines, Kotlin Multiplatform, and modern JVM development.

Core Concepts

Kotlin Fundamentals

  • Null safety

  • Extension functions

  • Data classes

  • Sealed classes

  • Coroutines and Flow

  • Higher-order functions

Android Development

  • Jetpack Compose

  • ViewModel and LiveData

  • Room database

  • Retrofit networking

  • Dependency injection (Hilt)

  • Android lifecycle

Kotlin Multiplatform

  • Shared business logic

  • Platform-specific implementations

  • iOS and Android targets

  • Common module architecture

Modern Kotlin Syntax

// Data classes data class User( val id: String, val name: String, val email: String, val createdAt: LocalDateTime = LocalDateTime.now() )

// Sealed classes for type-safe states sealed class Result<out T> { data class Success<T>(val data: T) : Result<T>() data class Error(val exception: Exception) : Result<Nothing>() object Loading : Result<Nothing>() }

// Extension functions fun String.isValidEmail(): Boolean { return this.contains("@") && this.contains(".") }

// Scope functions fun processUser(user: User) { user.run { println("Processing user: $name") // 'this' refers to user }

user.let { u ->
    // 'it' or custom name refers to user
    println(u.email)
}

user.apply {
    // Modify properties
    // Returns the object
}

}

// Null safety fun findUser(id: String): User? { return database.find(id) }

val user = findUser("123") val name = user?.name ?: "Unknown" // Elvis operator user?.let { println(it.name) } // Safe call with let

// When expression fun getUserStatus(user: User): String = when { user.isActive && user.isPremium -> "Premium Active" user.isActive -> "Active" else -> "Inactive" }

Coroutines and Flow

import kotlinx.coroutines.* import kotlinx.coroutines.flow.*

class UserRepository { private val api: UserApi

// Suspend function
suspend fun fetchUser(id: String): User {
    return withContext(Dispatchers.IO) {
        api.getUser(id)
    }
}

// Flow for reactive streams
fun observeUsers(): Flow&#x3C;List&#x3C;User>> = flow {
    while (true) {
        val users = fetchUsers()
        emit(users)
        delay(5000) // Refresh every 5 seconds
    }
}.flowOn(Dispatchers.IO)

// StateFlow for state management
private val _users = MutableStateFlow&#x3C;List&#x3C;User>>(emptyList())
val users: StateFlow&#x3C;List&#x3C;User>> = _users.asStateFlow()

suspend fun refreshUsers() {
    _users.value = fetchUsers()
}

}

// Coroutine scopes class UserViewModel : ViewModel() { private val repository = UserRepository()

fun loadUsers() {
    viewModelScope.launch {
        try {
            val users = repository.fetchUser("123")
            // Update UI
        } catch (e: Exception) {
            // Handle error
        }
    }
}

// Parallel execution
suspend fun loadMultipleUsers(ids: List&#x3C;String>): List&#x3C;User> {
    return coroutineScope {
        ids.map { id ->
            async { repository.fetchUser(id) }
        }.awaitAll()
    }
}

// Flow transformation
fun searchUsers(query: String): Flow&#x3C;List&#x3C;User>> {
    return repository.observeUsers()
        .map { users -> users.filter { it.name.contains(query, ignoreCase = true) } }
        .distinctUntilChanged()
        .debounce(300)
}

}

Android Jetpack Compose

import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier

@Composable fun UserListScreen(viewModel: UserViewModel = viewModel()) { val users by viewModel.users.collectAsState() val isLoading by viewModel.isLoading.collectAsState()

Scaffold(
    topBar = { TopAppBar(title = { Text("Users") }) }
) { padding ->
    if (isLoading) {
        CircularProgressIndicator(
            modifier = Modifier.fillMaxSize()
        )
    } else {
        LazyColumn(
            modifier = Modifier.padding(padding)
        ) {
            items(users) { user ->
                UserCard(user = user)
            }
        }
    }
}

}

@Composable fun UserCard(user: User) { Card( modifier = Modifier .fillMaxWidth() .padding(8.dp) ) { Column(modifier = Modifier.padding(16.dp)) { Text( text = user.name, style = MaterialTheme.typography.headlineSmall ) Text( text = user.email, style = MaterialTheme.typography.bodyMedium ) } } }

Room Database

import androidx.room.* import kotlinx.coroutines.flow.Flow

@Entity(tableName = "users") data class UserEntity( @PrimaryKey val id: String, @ColumnInfo(name = "name") val name: String, @ColumnInfo(name = "email") val email: String, @ColumnInfo(name = "created_at") val createdAt: Long )

@Dao interface UserDao { @Query("SELECT * FROM users") fun getAllUsers(): Flow<List<UserEntity>>

@Query("SELECT * FROM users WHERE id = :userId")
suspend fun getUserById(userId: String): UserEntity?

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUser(user: UserEntity)

@Update
suspend fun updateUser(user: UserEntity)

@Delete
suspend fun deleteUser(user: UserEntity)

@Query("DELETE FROM users WHERE id = :userId")
suspend fun deleteUserById(userId: String)

}

@Database(entities = [UserEntity::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao

companion object {
    @Volatile
    private var INSTANCE: AppDatabase? = null

    fun getDatabase(context: Context): AppDatabase {
        return INSTANCE ?: synchronized(this) {
            val instance = Room.databaseBuilder(
                context.applicationContext,
                AppDatabase::class.java,
                "app_database"
            ).build()
            INSTANCE = instance
            instance
        }
    }
}

}

Dependency Injection with Hilt

import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import javax.inject.Singleton

@Module @InstallIn(SingletonComponent::class) object NetworkModule {

@Provides
@Singleton
fun provideRetrofit(): Retrofit {
    return Retrofit.Builder()
        .baseUrl("https://api.example.com")
        .addConverterFactory(GsonConverterFactory.create())
        .build()
}

@Provides
@Singleton
fun provideUserApi(retrofit: Retrofit): UserApi {
    return retrofit.create(UserApi::class.java)
}

}

@HiltAndroidApp class MyApplication : Application()

@AndroidEntryPoint class MainActivity : ComponentActivity() { @Inject lateinit var repository: UserRepository }

Kotlin Multiplatform

// commonMain expect class Platform() { val name: String }

expect fun platformSpecificFunction(): String

// androidMain actual class Platform actual constructor() { actual val name: String = "Android ${android.os.Build.VERSION.SDK_INT}" }

actual fun platformSpecificFunction(): String = "Android implementation"

// iosMain actual class Platform actual constructor() { actual val name: String = UIDevice.currentDevice.systemName() }

actual fun platformSpecificFunction(): String = "iOS implementation"

// Shared business logic class UserService { suspend fun fetchUser(id: String): User { // Shared logic works on all platforms return api.getUser(id) } }

Best Practices

Kotlin Style

  • Use val over var when possible

  • Leverage null safety features

  • Use data classes for DTOs

  • Prefer extension functions

  • Use sealed classes for type-safe states

  • Follow naming conventions

Coroutines

  • Use appropriate dispatchers (IO, Main, Default)

  • Handle cancellation properly

  • Avoid GlobalScope

  • Use structured concurrency

  • Prefer Flow over LiveData

  • Use StateFlow for state

Android

  • Follow MVVM architecture

  • Use Jetpack Compose for UI

  • Implement proper lifecycle handling

  • Use dependency injection

  • Handle configuration changes

  • Implement proper error handling

Anti-Patterns

❌ Using !! (non-null assertion) ❌ GlobalScope.launch ❌ Blocking main thread ❌ Not handling coroutine cancellation ❌ Tight coupling ❌ God classes ❌ Ignoring memory leaks

Resources

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

python-expert

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

devops-expert

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

code-review-expert

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

typescript-expert

No summary provided by upstream source.

Repository SourceNeeds Review