跳到主要内容

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,应逐步迁移到协程。迁移步骤:

  1. 将 AsyncTask 的 doInBackground 提取为 suspend 函数
  2. 在 ViewModel 中使用 viewModelScope.launch + withContext(Dispatchers.IO) 调用
  3. 用 StateFlow 替代 onPostExecute 的 UI 更新

常见面试问题

Q1: AsyncTask 和协程的核心区别?

答案

特性AsyncTask协程
生命周期感知✅ viewModelScope 自动取消
取消机制不可靠协作式取消,自动传播
异常处理难以传递try-catch + sealed class
内存泄漏常见(持有 Activity)viewModelScope 避免
串行/并行默认串行async 灵活控制
学习曲线中等

相关链接