Android中onResume启动的异步任务未完成时如何处理依赖它的按钮点击
实现方案
以下两种方案均适配你的需求,可根据项目技术栈选择:
方案1:LiveData实现(Java/Kotlin通用,无需修改原有Java异步逻辑)
核心思路是通过LiveData持有异步任务的完成状态,同时用布尔值标记按钮点击状态,任务完成后统一触发逻辑:
- 定义状态变量
// 异步任务状态:null=未完成,true=执行成功,false=执行失败 private val asyncTaskState = MutableLiveData<Boolean?>() // 按钮点击标记 private var isButtonClicked = false
onResume中触发异步任务并更新状态
override fun onResume() { super.onResume() asyncTaskState.value = null // 每次进入页面重置状态 // 启动原有异步任务 YourAsyncTask(object : TaskCallback { override fun onSuccess() { asyncTaskState.postValue(true) } override fun onFailure() { asyncTaskState.postValue(false) } }).execute() }
- 按钮点击事件处理
btnAction.setOnClickListener { when (asyncTaskState.value) { null -> { // 任务未完成:展示进度条,标记已点击 progressBar.visibility = View.VISIBLE isButtonClicked = true } else -> { // 任务已完成:直接执行后续逻辑 doButtonAction(asyncTaskState.value!!) } } }
- 观察任务状态,任务完成后自动触发等待中的按钮逻辑
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) asyncTaskState.observe(viewLifecycleOwner) { isSuccess -> isSuccess ?: return@observe // 隐藏进度条 progressBar.visibility = View.GONE // 如果按钮已被点击,执行后续逻辑 if (isButtonClicked) { doButtonAction(isSuccess) isButtonClicked = false // 重置标记 } } }
- 封装按钮后续逻辑
private fun doButtonAction(taskSuccess: Boolean) { if (taskSuccess) { // 异步任务成功时的按钮逻辑 } else { // 异步任务失败时的按钮逻辑,比如错误提示 } }
提示:Java项目可完全复用上述逻辑,仅需替换为Java语法即可。
方案2:Kotlin协程实现(纯Kotlin项目更简洁)
核心思路是用Deferred包装异步任务,点击按钮时直接await等待任务完成,无需额外维护点击标记:
- 定义变量
private var asyncTaskDeferred: Deferred<Boolean>? = null private val lifecycleScope by viewLifecycleOwner.lifecycleScope
onResume中用协程封装原有异步任务
override fun onResume() { super.onResume() asyncTaskDeferred = lifecycleScope.async { suspendCoroutine<Boolean> { continuation -> // 原有异步任务 YourAsyncTask(object : TaskCallback { override fun onSuccess() = continuation.resume(true) override fun onFailure() = continuation.resume(false) }).execute() } } }
- 按钮点击事件处理
btnAction.setOnClickListener { lifecycleScope.launch { progressBar.visibility = View.VISIBLE // 等待异步任务完成,未完成时自动挂起,不会阻塞主线程 val taskSuccess = asyncTaskDeferred?.await() ?: false progressBar.visibility = View.GONE // 直接执行后续逻辑 doButtonAction(taskSuccess) } }
注意事项
- 两种方案均绑定Fragment生命周期,页面销毁时自动取消观察/协程任务,不会产生内存泄漏
- 若需要支持任务重试,每次重新触发异步任务时重置对应状态变量即可
- 若异步任务可取消,可在
onPause中添加任务取消逻辑,减少不必要的资源消耗
内容的提问来源于stack exchange,提问作者Saurabh Somani
相关产品推荐
相关产品推荐

