如何取消旧AsyncTask并创建新任务?执行报错求助
解决AsyncTask重复执行的错误
你遇到的这个错误核心原因很明确:AsyncTask的实例只能被执行一次——不管它是正常完成、被取消还是中途失败,都不能再调用execute()方法。你的代码里复用了同一个getBoundedMomentsTask实例,所以第一次执行后,再调用execute()就会抛出这个异常。
修复方案:每次创建新的AsyncTask实例
我们需要修改代码逻辑,每次启动任务时都生成一个新的BoundsRequestTask对象,而不是复用旧的。具体步骤如下:
- 将任务变量改为可空类型,允许它在没有运行任务时为
null - 在启动新任务前,先取消当前可能在运行的旧任务
- 创建新的任务实例并执行它
修改后的代码如下:
// 改为可空变量,初始值为null var getBoundedMomentsTask : BoundsRequestTask? = null fun queryMapMoments(bounds : LatLngBounds, zoom : Float ) { // 取消当前正在运行的任务 getBoundedMomentsTask?.apply { if (status == AsyncTask.Status.RUNNING) { cancel(true) } } // 创建新的任务实例 getBoundedMomentsTask = BoundsRequestTask() // 执行新任务 getBoundedMomentsTask?.execute(BoundsTaskParams(bounds, zoom)) } inner class BoundsRequestTask : AsyncTask<BoundsTaskParams, Void, List<Moment>>() { override fun doInBackground(vararg params: BoundsTaskParams?): List<Moment> { // 第一步就检查是否被取消,避免做无用功 if (isCancelled) return mutableListOf() val bounds: LatLngBounds? = params[0]?.bounds val zoom: Float? = params[0]?.zoom Log.d("doInBackground", "Getting map channel") val channel = checkMapChannels(bounds, zoom) if (isCancelled) return mutableListOf() Log.d("doInBackground", "Asking for moments from database") channel.fetchDatabaseMoments() if (isCancelled) return mutableListOf() if (!channel.networkRequested) { Log.d("doInBackground", "Asking for moments from network") channel.fetchMomentsOnNetwork() if (isCancelled) return mutableListOf() } Log.d("doInBackground", "Saving the returned channel") channels.add(channel) return channel.regionMoments } override fun onPostExecute(list : List<Moment>) { // 这里也要检查任务是否被取消,避免更新已经过时的结果 if (!isCancelled) { mappedMoments.value = list } } }
额外注意事项
- 在
doInBackground中,要在每个耗时操作前后都检查isCancelled(),确保任务被取消后能立刻停止执行,避免浪费资源。 - 在
onPostExecute里也要检查isCancelled(),因为即使任务被取消,onPostExecute仍有可能被调用(取决于取消时机),这时候不要更新LiveData,避免给UI传递过时的数据。
关于AsyncTask的替代建议
另外要提醒你,AsyncTask已经被Android官方弃用了,推荐使用Kotlin协程(Coroutines)来处理异步任务,它的写法更简洁,也更容易管理任务的取消和生命周期。如果后续有机会重构代码,可以考虑切换到协程,比如用viewModelScope或者lifecycleScope来自动管理任务的生命周期,避免内存泄漏。
内容的提问来源于stack exchange,提问作者chrisdottel
相关产品推荐
相关产品推荐

