做安卓开发的朋友都知道,处理网络请求、数据库读写这些事,一不小心就会卡住主线程,页面直接变“僵尸”——点不动也动不了。以前用回调,代码一层套一层,看得人脑壳疼;后来上了RxJava,学习成本又高。直到Kotlin协程出现,才真正感觉松了口气。
\n\n但协程用多了也会发现问题:每次都要写 repeatOnLifecycle、launch、try-catch,重复代码一堆。就像家里做饭,每次切菜都得从磨刀开始,太费劲。于是我就琢磨,能不能把常用的协程操作打包成一个“工具箱”,用的时候直接拎出来就行?
\n\n为啥要封装协程?
\n\n举个例子,你做个App,首页要从服务器拉数据,刷新列表。每次写一遍 launch + try-catch + loading状态控制,三个月下来自己都懒得看这代码。而且一旦忘了加异常处理,用户点一下就崩,体验差得很。
\n\n如果能把“启动协程、自动绑定生命周期、出错自动兜底、加载中提示”这些事一次性封装好,以后只要关心“我要拿什么数据”就行了,其他杂事全交给包装函数。
\n\n简单封装一个扩展函数
\n\n我在项目里常写这样一个扩展函数,专门处理UI层的异步任务:
\n\nfun CoroutineScope.launchSilent(\n block: suspend CoroutineScope.() -> Unit\n) {\n launch {\n try {\n block()\n } catch (e: Exception) {\n // 可以统一上报错误,或者弹个Toast\n e.printStackTrace()\n }\n }\n}\n\n然后在Activity或Fragment里直接用:
\n\nlifecycleScope.launchSilent {\n val data = repository.fetchUserData()\n updateUI(data)\n}\n\n连 try-catch 都不用写了,出错了也不会崩溃,后台默默记一笔,用户体验稳了不少。
\n\n带状态反馈的封装更实用
\n\n实际开发中,loading、成功、失败这三种状态几乎绕不开。可以再进一步,把状态也封装进去:
\n\nsealed class Result<out T> {\n data class Success<T>(val data: T) : Result<T>()\n data class Error(val exception: Exception) : Result<Nothing>()\n object Loading : Result<Nothing>()\n}\n\n然后写个通用方法:
\n\nfun <T> CoroutineScope.launchWithResult(\n onResult: (Result<T>) -> Unit,\n block: suspend () -> T\n) {\n launch {\n onResult(Result.Loading)\n try {\n val result = block()\n onResult(Result.Success(result))\n } catch (e: Exception) {\n onResult(Result.Error(e))\n }\n }\n}\n\n调用时清晰明了:
\n\nlifecycleScope.launchWithResult(\n onResult = { result ->\n when (result) {\n is Result.Loading -> showLoading()\n is Result.Success -> updateList(result.data)\n is Result.Error -> showErrorToast()\n }\n }\n) {\n apiService.getData()\n}\n\n这种写法,团队新人也能一眼看懂流程,沟通成本低了很多。
\n\n结合ViewModel更顺手
\n\n在 MVVM 架构里,ViewModel 是协程的好搭档。我通常会在基类里提供一个安全发射函数:
\n\nabstract class BaseViewModel : ViewModel() {\n protected fun <T> liveData(block: suspend LiveDataScope<T>.() -> Unit): LiveData<T> =\n liveData(viewModelScope.coroutineContext + Dispatchers.IO) {\n try {\n block()\n } catch (e: Exception) {\n // 统一错误处理\n }\n }\n}\n\n子类直接用:
\n\nval userInfo = liveData {\n emit(repository.loadUserInfo())\n}\n\n一行代码搞定异步转LiveData,不用再手动 postValue,也不怕内存泄漏。
\n\n这些封装不是一上来就设计完美的,而是从一个个痛点慢慢攒出来的。就像家里的收纳盒,东西用多了,才知道怎么分门别类最顺手。代码也一样,封装得好,天天写代码也能像回家吃饭一样踏实。”,"seo_title":"Kotlin协程封装技巧 - 提升Android开发效率","seo_description":"通过实际案例讲解如何封装Kotlin协程,减少重复代码,提升Android开发效率和代码可读性,适合日常项目使用。","keywords":"Kotlin协程封装, Android协程使用, 协程扩展函数, 异步编程, Kotlin开发技巧"}