agentsclimarketplace

Kotlin patterns

Skill thetruong1099/android-mvi-base-code/.claude/skills/kotlin-patterns

Install
npx -y skills add thetruong1099/android-mvi-base-code --skill kotlin-patterns

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Kotlin coding patterns for this project. Provides guidance on scope functions, collection operations with sequences, sealed class handling, extension functions, coroutine patterns, null safety, and data class usage. Automatically applied when writing Kotlin code in this codebase.

SKILL.md

3.8 KB, as published. Nobody here has run it

Kotlin Patterns

Scope Functions

// let - null check + transform
val name = user?.let { "${it.firstName} ${it.lastName}" } ?: "Unknown"

// run - execute block on object
val result = item.run { copy(name = name.trim()) }

// apply - configure object
val config = PagingConfig(pageSize = 20).apply { enablePlaceholders = false }

// also - side effects (logging, analytics)
fun getItem(id: String) = repository.getItem(id).also { Log.d(TAG, "Fetched: $id") }

// with - operate on object without chaining
with(viewModel) {
    setState { copy(isLoading = false) }
    showSuccessToast(R.string.saved)
}

Collection Operations

// Prefer sequence for large collections with multiple operations
items.asSequence()
    .filter { it.isActive }
    .sortedByDescending { it.updatedAt }
    .take(10)
    .toList()

val itemsByCategory = items.groupBy { it.category }         // groupBy for categorization
val itemById = items.associateBy { it.id }                  // associate for map creation
val (favorites, others) = items.partition { it.isFavorite } // partition for splitting

Sealed Classes & When Expressions

// Always use exhaustive when for sealed types
when (error) {
    is AppError.NoInternetConnection -> showOfflineUI()
    is AppError.NetworkTimeout       -> showRetryButton()
    is AppError.ServerError          -> showServerError(error.statusCode)
    is AppError.DataParsingError     -> logAndShowGenericError()
    is AppError.Unauthorized         -> navigateToLogin()
    is AppError.Unknown              -> showGenericError()
}
// Compiler errors if new AppError subclass is added but not handled

Extension Functions

// Good: focused, reusable extensions
fun Modifier.noRippleClickable(onClick: () -> Unit): Modifier

fun NavHostController.navigateTo(route: Any, builder: NavOptionsBuilder.() -> Unit = {})

val MaterialTheme.spacing: Spacing @Composable get() = LocalSpacing.current

// Avoid: over-broad extensions
// fun Any.toJson(): String  // Too broad

Coroutine Patterns

// Use viewModelScope for ViewModel operations
viewModelScope.launch {
    collectDataStateWithInternet(
        callFlow = useCase(params),
        onSuccess = { setState { copy(data = it) } },
        onError = { showErrorToast(it) },
    )
}

// Use withContext for dispatcher switching
suspend fun parseHtml(html: String): String = withContext(Dispatchers.Default) {
    Jsoup.parse(html).text()
}

// Prefer Flow operators over manual coroutine management
useCase()
    .catch { emit(DataState.Error(mapError(it))) }
    .collect { /* handle */ }

Null Safety

val displayName = item.author ?: "Unknown Author"                            // Elvis for defaults
item?.chapters?.firstOrNull()?.let { navigateToChapter(it) }                // Safe calls

// Avoid !! - use require/check for assertions
fun processItem(item: Item?) {
    requireNotNull(item) { "Item must not be null" }
    // item is smart-cast to non-null
}

Data Classes

// Use copy() for immutable updates (MVI pattern)
setState { copy(isLoading = true, error = null) }

// Destructuring in lambdas
items.map { (id, name, author) -> "$name by $author" }

// Default values for flexibility
data class SampleViewState(
    val items: Flow<PagingData<SampleModel>>? = null,
    val isRefreshing: Boolean = false,
) : IViewState

// Type aliases for complex generics
typealias ItemPagingFlow = Flow<PagingData<Item>>
typealias DataStateFlow<T> = Flow<DataState<T>>

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.