AsyncTask(已废弃)
问题
AsyncTask 为什么被废弃?它存在哪些问题?
答案
AsyncTask 基本结构
// AsyncTask 典型用法(已废弃,仅供了解)
class DownloadTask : AsyncTask<String, Int, String>() {
override fun onPreExecute() {
// 主线程:显示进度条
}
override fun doInBackground(vararg urls: String): String {
// 后台线程:执行耗时操作
val result = downloadFile(urls[0])
publishProgress(50) // 发布进度
return result
}
override fun onProgressUpdate(vararg values: Int?) {
// 主线程:更新进度
}
override fun onPostExecute(result: String) {
// 主线程:显示结果
}
}
被废弃的核心原因
| 问题 | 说明 |
|---|---|
| 内存泄漏 | 作为内部类隐式持有 Activity 引用,Activity 销毁后任务仍在执行 |
| 生命周期不感知 | 不知道 Activity/Fragment 是否还存活,onPostExecute 可能更新已销毁的 View |
| 取消不可靠 | cancel(true) 只是设置标志位,doInBackground 需要手动检查 isCancelled() |
| 串行执行 | API 13+ 默认使用 SERIAL_EXECUTOR,多任务串行,容易造成阻塞 |
| 结果丢失 | 配置变更(如旋转屏幕)后,任务结果无法传递给新 Activity |
| 异常处理弱 | doInBackground 异常没有好的传递机制 |
替代方案对比
// ❌ AsyncTask(废弃)
class LoadDataTask(private val activity: MyActivity) :
AsyncTask<Void, Void, List<User>>() {
override fun doInBackground(vararg params: Void?): List<User> {
return api.getUsers()
}
override fun onPostExecute(result: List<User>) {
activity.showUsers(result) // Activity 可能已销毁!
}
}
// ✅ 协程 + ViewModel(推荐)
class UserViewModel : ViewModel() {
private val _users = MutableStateFlow<List<User>>(emptyList())
val users: StateFlow<List<User>> = _users.asStateFlow()
fun loadUsers() {
viewModelScope.launch {
val result = withContext(Dispatchers.IO) {
api.getUsers()
}
_users.value = result // viewModelScope 自动管理生命周期
}
}
}
提示
如果维护老项目遇到 AsyncTask,应逐步迁移到协程。迁移步骤:
- 将 AsyncTask 的
doInBackground提取为suspend函数 - 在 ViewModel 中使用
viewModelScope.launch+withContext(Dispatchers.IO)调用 - 用 StateFlow 替代
onPostExecute的 UI 更新
常见面试问题
Q1: AsyncTask 和协程的核心区别?
答案:
| 特性 | AsyncTask | 协程 |
|---|---|---|
| 生命周期感知 | ❌ | ✅ viewModelScope 自动取消 |
| 取消机制 | 不可靠 | 协作式取消,自动传播 |
| 异常处理 | 难以传递 | try-catch + sealed class |
| 内存泄漏 | 常见(持有 Activity) | viewModelScope 避免 |
| 串行/并行 | 默认串行 | async 灵活控制 |
| 学习曲线 | 低 | 中等 |