Token导航 LogoToken导航

Agent Skill · AI 工具

kotlin-coroutines(Kotlin 协程)

kotlin-coroutines 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

kotlin-coroutines 是AI 工具类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证为 MIT,第三方扫描已通过,按安装量在AI 工具类的 2,536 个 Skill 里排第 483。

总安装 4,264周安装 240GitHub Stars 142下载 2,476核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:kotlin-coroutines(Kotlin 协程)
来源仓库:https://github.com/thebushidocollective/han
仓库路径:skills/kotlin-coroutines
安装命令:
npx skills add https://github.com/thebushidocollective/han --skill 'Kotlin Coroutines'
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/thebushidocollective/han --skill 'Kotlin Coroutines'

这个 Skill 是做什么的

AI 工具类 Skill 用来扩展助手本身的能力,例如接模型、接检索、接外部服务。

kotlin-coroutines 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息。适合在 Codex、Claude、Cursor、Gemini CLI 中围绕仓库状态、代码变更或协作事项进行整理。通过 npx skills add 命令从指定 GitHub 路径安装并使用。

安装前需确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。建议结合来源仓库和原始 README 核验具体用法和功能边界。

来源仓库内路径:skills/kotlin-coroutines

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/thebushidocollective/han --skill 'Kotlin Corou…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

kotlin-coroutines 怎么安装?

在终端执行 npx skills add https://github.com/thebushidocollective/han --skill 'Kotlin Coroutines'。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

kotlin-coroutines 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

kotlin-coroutines 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

kotlin-coroutines 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

kotlin-coroutines 用的人多吗?

公开数据是累计安装 4,264 次,近一周安装 240 次,下载 2,476 次,GitHub 142 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

kotlin-coroutines 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理AI 工具类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

AI 工具类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
executing-plans

执行计划 · Codex、Claude

1,515,336173,110只读MIT通过
verification-before-completion

完成前的验证 · Codex、Claude

1,319,472173,121权限未标注MIT通过
subagent-driven-development

子 Agent 驱动开发 · Codex、Claude

1,312,416173,138只读MIT通过
copy-editing

复制编辑 · Codex、Claude

1,209,57625,632只读MIT通过
paywall-upgrade-cro

付费专区升级 cro · Codex、Claude

1,030,17625,617只读MIT通过
kotlin-coroutines

Kotlin 协程 · 本页

4,264142需要联网MIT通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Kotlin Coroutines

Introduction

Kotlin coroutines provide a powerful framework for asynchronous programming that is lightweight, expressive, and built on structured concurrency principles. Coroutines enable writing asynchronous code that looks and behaves like sequential code, eliminating callback hell and improving readability.

Unlike threads, coroutines are extremely lightweight—millions can run on limited resources. The coroutine framework includes suspend functions for non-blocking operations, builders for launching work, Flow for reactive streams, and comprehensive cancellation and exception handling mechanisms.

This skill covers coroutine fundamentals, builders, contexts, Flow, channels, and production patterns for Android development and server-side Kotlin.

Suspend Functions

Suspend functions are the building blocks of coroutines, enabling non-blocking operations that can be paused and resumed without blocking threads.

// Basic suspend function
suspend fun fetchUser(id: Int): User {
    delay(1000) // Suspends without blocking
    return User(id, "Alice")
}

data class User(val id: Int, val name: String)

// Calling suspend functions
suspend fun loadUserProfile(id: Int): UserProfile {
    val user = fetchUser(id)
    val posts = fetchPosts(user.id)
    return UserProfile(user, posts)
}

suspend fun fetchPosts(userId: Int): List<Post> {
    delay(500)
    return emptyList()
}

data class Post(val id: Int, val title: String)
data class UserProfile(val user: User, val posts: List<Post>)

// Sequential vs concurrent execution
suspend fun loadDataSequential(): Pair<User, List<Post>> {
    val user = fetchUser(1)
    val posts = fetchPosts(1)
    return user to posts
}

suspend fun loadDataConcurrent(): Pair<User, List<Post>> = coroutineScope {
    val userDeferred = async { fetchUser(1) }
    val postsDeferred = async { fetchPosts(1) }
    userDeferred.await() to postsDeferred.await()
}

// Suspend functions with callbacks
suspend fun fetchData(url: String): String = suspendCoroutine { continuation ->
    fetchDataWithCallback(url) { result, error ->
        if (error != null) {
            continuation.resumeWithException(error)
        } else {
            continuation.resume(result)
        }
    }
}

fun fetchDataWithCallback(
    url: String,
    callback: (String, Exception?) -> Unit
) {
    // Simulated callback-based API
    callback("data", null)
}

// Cancellable suspend functions
suspend fun downloadFile(url: String): ByteArray =
    suspendCancellableCoroutine { continuation ->
        val request = startDownload(url) { data, error ->
            if (error != null) {
                continuation.resumeWithException(error)
            } else {
                continuation.resume(data)
            }
        }

        continuation.invokeOnCancellation {
            request.cancel()
        }
    }

class DownloadRequest {
    fun cancel() {}
}

fun startDownload(url: String, callback: (ByteArray, Exception?) -> Unit):
    DownloadRequest {
    return DownloadRequest()
}

// Using withContext for dispatcher switching
suspend fun saveToDatabase(user: User) {
    withContext(Dispatchers.IO) {
        // Database operation on IO dispatcher
        println("Saving user: ${user.name}")
    }
}

suspend fun updateUI(user: User) {
    withContext(Dispatchers.Main) {
        // UI update on main thread
        println("Updating UI for: ${user.name}")
    }
}

Suspend functions are marked with the suspend modifier and can only be called from other suspend functions or coroutines, ensuring proper context.

Coroutine Builders

Coroutine builders launch coroutines with different lifecycle and result handling semantics, enabling structured and unstructured concurrency.

// launch: fire-and-forget coroutine
fun launchExample() {
    GlobalScope.launch {
        val user = fetchUser(1)
        println("User: ${user.name}")
    }
}

// async: coroutine with result
fun asyncExample() {
    GlobalScope.launch {
        val deferredUser = async { fetchUser(1) }
        val deferredPosts = async { fetchPosts(1) }

        val user = deferredUser.await()
        val posts = deferredPosts.await()

        println("Loaded ${posts.size} posts for ${user.name}")
    }
}

// runBlocking: bridges blocking and suspending worlds
fun runBlockingExample() = runBlocking {
    val user = fetchUser(1)
    println("User loaded: ${user.name}")
}

// coroutineScope: structured concurrency
suspend fun loadMultipleUsers(ids: List<Int>): List<User> = coroutineScope {
    ids.map { id ->
        async { fetchUser(id) }
    }.awaitAll()
}

// supervisorScope: independent child failures
suspend fun loadDataWithSupervisor(): List<User> = supervisorScope {
    val user1 = async { fetchUser(1) }
    val user2 = async {
        delay(100)
        throw Exception("Failed")
    }

    // user1 succeeds even if user2 fails
    listOfNotNull(
        try { user1.await() } catch (e: Exception) { null }
    )
}

// withTimeout: time-limited coroutines
suspend fun fetchWithTimeout(id: Int): User? {
    return try {
        withTimeout(2000) {
            fetchUser(id)
        }
    } catch (e: TimeoutCancellationException) {
        null
    }
}

// Structured concurrency with lifecycle
class ViewModel : CoroutineScope {
    private val job = SupervisorJob()
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job

    fun loadData() {
        launch {
            val user = fetchUser(1)
            // Update UI
        }
    }

    fun onCleared() {
        job.cancel()
    }
}

Structured concurrency with coroutineScope ensures child coroutines complete before the scope exits, preventing leaks and ensuring proper cleanup.

Coroutine Context and Dispatchers

Coroutine context defines the execution environment including dispatcher, job, exception handler, and coroutine name for debugging.

// Dispatchers for thread pools
suspend fun dispatcherExamples() {
    // Main: UI thread (Android/JavaFX)
    withContext(Dispatchers.Main) {
        println("On main thread: ${Thread.currentThread().name}")
    }

    // IO: for blocking I/O operations
    withContext(Dispatchers.IO) {
        println("On IO thread: ${Thread.currentThread().name}")
    }

    // Default: CPU-intensive work
    withContext(Dispatchers.Default) {
        println("On default thread: ${Thread.currentThread().name}")
    }

    // Unconfined: starts in caller thread, resumes where suspended
    withContext(Dispatchers.Unconfined) {
        println("Unconfined: ${Thread.currentThread().name}")
    }
}

// Coroutine context elements
fun contextExample() {
    val scope = CoroutineScope(
        Dispatchers.Main +
        SupervisorJob() +
        CoroutineName("MyCoroutine") +
        CoroutineExceptionHandler { _, throwable ->
            println("Caught: $throwable")
        }
    )

    scope.launch {
        println("Context: $coroutineContext")
    }
}

// Inheriting context
fun inheritContextExample() {
    CoroutineScope(Dispatchers.Main).launch {
        println("Parent: ${Thread.currentThread().name}")

        launch {
            // Inherits Dispatchers.Main
            println("Child: ${Thread.currentThread().name}")
        }

        launch(Dispatchers.IO) {
            // Overrides with IO dispatcher
            println("Override: ${Thread.currentThread().name}")
        }
    }
}

// ThreadLocal context element
val threadLocalValue = ThreadLocal<String>()

suspend fun threadLocalExample() {
    threadLocalValue.set("initial")

    withContext(threadLocalValue.asContextElement("new value")) {
        println("In context: ${threadLocalValue.get()}")
    }

    println("After context: ${threadLocalValue.get()}")
}

// Custom context element
data class UserId(val id: Int) : AbstractCoroutineContextElement(Key) {
    companion object Key : CoroutineContext.Key<UserId>
}

suspend fun customContextExample() {
    withContext(UserId(42)) {
        val userId = coroutineContext[UserId]
        println("User ID: ${userId?.id}")
    }
}

Dispatchers determine which thread pool executes the coroutine. Context elements are inherited by child coroutines and can be overridden.

Flow for Reactive Streams

Flow represents a cold stream of values that are computed on demand, providing reactive programming capabilities with backpressure and transformation operators.

// Basic Flow
fun numberFlow(): Flow<Int> = flow {
    for (i in 1..5) {
        delay(100)
        emit(i)
    }
}

suspend fun collectFlow() {
    numberFlow().collect { value ->
        println("Received: $value")
    }
}

// Flow builders
fun flowBuilders() {
    // flowOf: emit fixed values
    val fixedFlow = flowOf(1, 2, 3, 4, 5)

    // asFlow: convert collections
    val listFlow = listOf(1, 2, 3).asFlow()

    // flow: custom emission logic
    val customFlow = flow {
        repeat(3) {
            emit(it)
            delay(100)
        }
    }
}

// Flow transformations
suspend fun flowTransformations() {
    numberFlow()
        .map { it * 2 }
        .filter { it > 5 }
        .take(3)
        .collect { println(it) }
}

// Flow combining
suspend fun combineFlows() {
    val flow1 = flowOf(1, 2, 3)
    val flow2 = flowOf("A", "B", "C")

    // zip: pairs elements
    flow1.zip(flow2) { num, letter ->
        "$num$letter"
    }.collect { println(it) }

    // combine: latest from each
    flow1.combine(flow2) { num, letter ->
        "$num$letter"
    }.collect { println(it) }
}

// Flow exception handling
suspend fun flowExceptionHandling() {
    flow {
        emit(1)
        emit(2)
        throw Exception("Error!")
    }.catch { e ->
        println("Caught: ${e.message}")
        emit(-1)
    }.collect { println(it) }
}

// StateFlow and SharedFlow
class DataRepository {
    private val _users = MutableStateFlow<List<User>>(emptyList())
    val users: StateFlow<List<User>> = _users

    private val _events = MutableSharedFlow<Event>()
    val events: SharedFlow<Event> = _events

    suspend fun loadUsers() {
        val loaded = fetchUsers()
        _users.value = loaded
    }

    suspend fun emitEvent(event: Event) {
        _events.emit(event)
    }

    private suspend fun fetchUsers(): List<User> {
        delay(100)
        return listOf(User(1, "Alice"))
    }
}

data class Event(val type: String)

// Flow on different dispatchers
suspend fun flowWithContext() {
    flow {
        emit(1)
        emit(2)
    }
    .flowOn(Dispatchers.IO)
    .collect { value ->
        // Collected on caller's context
        println("Value: $value")
    }
}

// Channel Flow for hot streams
fun channelFlowExample() = channelFlow {
    launch {
        repeat(3) {
            send(it)
            delay(100)
        }
    }

    launch {
        repeat(3) {
            send(it * 10)
            delay(150)
        }
    }
}

Flow is cold—it doesn't execute until collected. StateFlow holds state, SharedFlow broadcasts events, and channelFlow enables concurrent emissions.

Channels for Communication

Channels provide communication primitives for sending and receiving values between coroutines, similar to BlockingQueue but suspending.

// Basic channel usage
suspend fun channelExample() {
    val channel = Channel<Int>()

    launch {
        for (x in 1..5) {
            channel.send(x)
        }
        channel.close()
    }

    for (y in channel) {
        println("Received: $y")
    }
}

// Buffered channels
fun bufferedChannelExample() {
    val channel = Channel<Int>(capacity = 4)

    GlobalScope.launch {
        for (x in 1..10) {
            println("Sending $x")
            channel.send(x)
        }
        channel.close()
    }

    GlobalScope.launch {
        delay(1000)
        for (y in channel) {
            println("Received: $y")
            delay(200)
        }
    }
}

// Channel types
fun channelTypes() {
    // Rendezvous: no buffer, sender suspends until receiver
    val rendezvous = Channel<Int>()

    // Buffered: specified capacity
    val buffered = Channel<Int>(10)

    // Unlimited: unlimited buffer
    val unlimited = Channel<Int>(Channel.UNLIMITED)

    // Conflated: keeps only latest value
    val conflated = Channel<Int>(Channel.CONFLATED)
}

// Produce builder
fun produceNumbers(): ReceiveChannel<Int> = GlobalScope.produce {
    for (x in 1..5) {
        send(x * x)
        delay(100)
    }
}

suspend fun consumeNumbers() {
    val channel = produceNumbers()
    channel.consumeEach { println(it) }
}

// Multiple consumers
suspend fun multipleConsumers() {
    val channel = Channel<Int>()

    repeat(3) { id ->
        launch {
            for (value in channel) {
                println("Consumer $id received: $value")
            }
        }
    }

    repeat(10) {
        channel.send(it)
        delay(100)
    }

    channel.close()
}

// Select expression for multiple channels
suspend fun selectExample() {
    val channel1 = produce { send("A") }
    val channel2 = produce { send("B") }

    select<Unit> {
        channel1.onReceive { value ->
            println("From channel1: $value")
        }
        channel2.onReceive { value ->
            println("From channel2: $value")
        }
    }
}

fun CoroutineScope.produce(block: suspend () -> Unit): ReceiveChannel<String> {
    return produce {
        block()
    }
}

Channels enable fan-out (multiple consumers), fan-in (multiple producers), and pipeline patterns for concurrent data processing.

Cancellation and Exception Handling

Coroutines support cooperative cancellation and structured exception handling to ensure proper resource cleanup and error propagation.

// Basic cancellation
suspend fun cancellationExample() {
    val job = GlobalScope.launch {
        repeat(1000) { i ->
            println("Working: $i")
            delay(500)
        }
    }

    delay(2000)
    println("Cancelling...")
    job.cancel()
    job.join()
    println("Cancelled")
}

// Checking for cancellation
suspend fun checkCancellation() {
    GlobalScope.launch {
        var i = 0
        while (isActive) {
            println("Computing: ${i++}")
        }
    }
}

// Non-cancellable work
suspend fun nonCancellableCleanup() {
    val job = GlobalScope.launch {
        try {
            repeat(1000) {
                delay(500)
            }
        } finally {
            withContext(NonCancellable) {
                println("Cleanup in non-cancellable context")
                delay(1000)
                println("Cleanup complete")
            }
        }
    }

    delay(1000)
    job.cancelAndJoin()
}

// Timeout handling
suspend fun timeoutExample() {
    try {
        withTimeout(1000) {
            repeat(100) {
                delay(100)
                println("Working...")
            }
        }
    } catch (e: TimeoutCancellationException) {
        println("Timed out")
    }
}

// Exception handling in coroutines
suspend fun exceptionHandlingExample() {
    val handler = CoroutineExceptionHandler { _, exception ->
        println("Caught: $exception")
    }

    GlobalScope.launch(handler) {
        throw Exception("Coroutine failed")
    }

    delay(100)
}

// Structured exception handling
suspend fun structuredExceptions() = coroutineScope {
    val job1 = launch {
        delay(100)
        throw Exception("Job 1 failed")
    }

    val job2 = launch {
        delay(200)
        println("Job 2 completed")
    }

    // job2 is cancelled when job1 fails
}

// SupervisorScope for independent failures
suspend fun supervisorExample() = supervisorScope {
    val job1 = launch {
        delay(100)
        throw Exception("Job 1 failed")
    }

    val job2 = launch {
        delay(200)
        println("Job 2 completed")
    }

    // job2 continues even if job1 fails
}

// Error handling with try-catch
suspend fun errorHandling() {
    coroutineScope {
        launch {
            try {
                fetchUser(1)
            } catch (e: Exception) {
                println("Error: ${e.message}")
            }
        }
    }
}

Cancellation is cooperative—coroutines must check isActive or call suspending functions. Exception handling respects structured concurrency boundaries.

Best Practices

  1. Use structured concurrency with scopes to ensure coroutines are properly managed and cancelled when no longer needed
  2. Choose appropriate dispatchers for the work type: IO for blocking operations, Default for CPU work, Main for UI updates
  3. Handle cancellation cooperatively by checking isActive in loops and using suspending functions that support cancellation
  4. Prefer Flow over callbacks for reactive streams to gain backpressure, operators, and structured lifecycle management
  5. Use supervisorScope for independent operations to prevent one failure from cancelling unrelated coroutines
  6. Avoid GlobalScope except for truly application-wide work to prevent leaks and maintain structured concurrency benefits
  7. Apply withContext for dispatcher switching instead of launching new coroutines to maintain structure and reduce overhead
  8. Handle exceptions explicitly with try-catch or CoroutineExceptionHandler to prevent silent failures
  9. Use StateFlow for state and SharedFlow for events to provide observable streams with proper lifecycle awareness
  10. Test coroutines with TestCoroutineDispatcher to control time and ensure deterministic test execution

Common Pitfalls

  1. Using GlobalScope for scoped work causes memory leaks when coroutines outlive their relevant context like activities or view models
  2. Blocking inside coroutines with Thread.sleep or blocking I/O defeats the purpose and can exhaust thread pools
  3. Not handling cancellation in long-running loops causes coroutines to continue executing after cancellation
  4. Forgetting suspend modifier on functions that call other suspend functions causes compilation errors
  5. Catching CancellationException and not rethrowing it prevents proper cancellation propagation in structured concurrency
  6. Using delay(0) to yield is less clear than explicitly calling yield() for cooperative multitasking
  7. Creating too many coroutines unnecessarily can degrade performance; batch or throttle operations when possible
  8. Not using withContext for dispatcher switching and instead launching unnecessary child coroutines adds complexity
  9. Assuming immediate execution after launch; coroutines may not start until dispatcher has capacity
  10. Mixing callbacks and coroutines incorrectly without proper bridging creates race conditions and leaks

When to Use This Skill

Use Kotlin coroutines when building Android applications for asynchronous operations like network calls, database queries, or any I/O-bound work that should not block the main thread.

Apply coroutines in server-side Kotlin applications with Ktor or Spring Boot for handling concurrent requests efficiently without thread-per-request overhead.

Employ Flow for reactive streams in MVVM architecture, replacing LiveData or RxJava for state management and event propagation with lifecycle awareness.

Leverage structured concurrency for coordinating multiple async operations, ensuring proper cancellation when navigating away from screens or closing connections.

Use channels for producer-consumer patterns, pipelines, or any scenario requiring explicit communication between concurrent coroutines.

Resources

平台分布

OpenCode

25.9%
按下载量换算641

Codex

24.13%
按下载量换算597

Claude Code

16.7%
按下载量换算413

windsurf

11.5%
按下载量换算285

Antigravity

7.57%
按下载量换算187

Gemini CLI

3.6%
按下载量换算89

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

继续浏览同类 Skills