软件帮帮网
柔彩主题三 · 更轻盈的阅读体验

Kotlin协程项目实例:用真实场景看懂高效异步编程

发布时间:2025-12-10 11:37:12 阅读:25 次

做安卓开发的应该都遇到过这种情况:点个按钮加载数据,界面卡住几秒,用户以为手机坏了。以前用线程切换来回折腾,代码嵌套得像迷宫。后来用了Kotlin协程,写异步代码跟写同步一样顺滑,尤其是结合实际项目,效果特别明显。

一个天气App的小例子

假设你正在做一个简单的天气应用,用户打开页面时,需要从网络获取当前城市气温,同时加载本地缓存的穿衣建议。这两个操作互不依赖,完全可以并行处理。

用传统的回调方式,你得开两个线程,再在主线程更新UI,一不小心就出错。而用协程,几行代码就能搞定:

viewModelScope.launch {
    val weatherDeferred = async { repository.fetchWeather() }
    val suggestionDeferred = async { repository.loadSuggestionFromLocal() }

    val weather = weatherDeferred.await()
    val suggestion = suggestionDeferred.await()

    updateUi(weather, suggestion)
}

这里用了 async 启动两个并发任务,await() 等结果回来。整个过程清晰明了,没有层层嵌套,也不会阻塞主线程。

处理异常也很自然

网络请求总可能失败。协程里可以直接用 try-catch 包住 launch 或 async 块,不用额外定义回调接口。

viewModelScope.launch {
    try {
        val data = async { apiService.getData() }.await()
        showData(data)
    } catch (e: Exception) {
        showError("加载失败,请检查网络")
    }
}

这种写法读起来就像在讲人话:试着去拿数据,拿到了就展示,出错了就提示。调试的时候也容易定位问题在哪一行。

实际项目中的结构建议

在真实项目中,别把所有协程逻辑堆在 Activity 或 Fragment 里。推荐把数据操作放在 Repository 层,用 suspend 函数封装:

class WeatherRepository {

    suspend fun getWeatherAndSuggestion(city: String): Result {
        return withContext(Dispatchers.IO) {
            val weather = fetchWeather(city)
            val suggestion = loadSuggestion(city)
            Result(weather, suggestion)
        }
    }

    private suspend fun fetchWeather(city: String): Weather { ... }
    private suspend fun loadSuggestion(city: String): Suggestion { ... }
}

ViewModel 里调用这个函数时,仍然是简洁的 suspend 调用,然后通过 StateFlow 或 LiveData 更新界面。这样分层清楚,测试也方便。

别忘了取消协程

用户点进页面开始加载,还没等结果就按返回键走了——这时候还在跑的协程得及时取消,不然可能造成内存泄漏或者空指针。用 viewModelScope 就很省心,它会随着 ViewModel 销毁自动取消所有子协程,不需要手动干预。

如果你自己创建 CoroutineScope,记得加上 Job 和超时控制:

val scope = CoroutineScope(Dispatchers.Main + Job())

// 页面销毁时调用
fun onDestroy() {
    scope.cancel()
}

协程不是魔法,但用对了真能少写很多“防御性代码”。现在新项目基本都默认上协程了,老项目也在逐步迁移。与其每次遇到异步就头疼,不如找个简单功能先练手,比如把登录请求改成 suspend 函数试试。