You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用从后台切回时下载进度Alert Dialog不显示如何解决?

问题根因
  • 核心是Activity生命周期与后台线程解绑+Dialog状态管理缺失:
  1. 当用户切后台时,系统可能因内存不足销毁当前Activity实例,切回时会重建新的Activity实例。你的后台线程持有的是旧Activity的alertDialog引用,旧实例已经不可见,更新旧Dialog自然不会在新Activity上展示。你在onResume中看到的null是新Activity的alertDialog变量,而后台线程访问的是旧实例的非null变量,这就是你观察到变量状态不一致的原因。
  2. 就算Activity没有重建,切后台时系统会自动dismiss关联的AlertDialog,但你没有监听dismiss事件将alertDialog变量置空,后续调用showDialogBox时会走else分支仅更改进度,不会重新调用show()展示弹窗。
  3. 你之前在onPause销毁弹窗但没重置alertDialog为null,也会导致同样的问题。
修复步骤

1. 优化Dialog状态管理

修改showDialogBox方法,添加Dialog dismiss监听,每次dismiss后自动重置alertDialog为null,确保后续需要时会重新创建弹窗:

private fun showDialogBox(progress: Int) {
    runOnUiThread {
        if (alertDialog == null) {
            val mDialogView = LayoutInflater.from(this).inflate(
                R.layout.cdfw_download_status_layout,
                null
            )
            val mBuilder = AlertDialog.Builder(this)
                .setView(mDialogView)
                .setCancelable(false)
            headingTv = mDialogView.findViewById(R.id.heading)
            headingSubTv = mDialogView.findViewById(R.id.heading_sub)
            closeButtonCdfw = mDialogView.findViewById(R.id.close_button)
            cdfwProgressBarForCdfwDilog = mDialogView.findViewById(R.id.progress_bar)
            cdfwProgressBarForCdfwDilog.progress = progress
            alertDialog = mBuilder.show()
            // 新增dismiss监听,重置变量
            alertDialog?.setOnDismissListener {
                alertDialog = null
                // 相关控件引用也同步置空,避免内存泄漏
                headingTv = null
                headingSubTv = null
                closeButtonCdfw = null
                cdfwProgressBarForCdfwDilog = null
            }
        } else {
            cdfwProgressBarForCdfwDilog?.progress = progress
        }
    }
}

2. 处理Activity重建场景

不要将下载进度和任务绑定到Activity实例,使用ViewModel存储下载状态与进度,ViewModel生命周期独立于Activity,重建时不会丢失数据:

// 新建DownloadViewModel.kt
class DownloadViewModel : ViewModel() {
    // 下载进度,用StateFlow或者LiveData都可以
    val downloadProgress = MutableStateFlow(0)
    // 标记下载是否进行中
    val isDownloading = MutableStateFlow(false)

    fun startDownload() {
        viewModelScope.launch(Dispatchers.IO) {
            isDownloading.value = true
            // 替换为你的Azure下载逻辑,每次进度更新时修改downloadProgress的值
            while (downloadProgress.value < 100) {
                delay(1000)
                downloadProgress.value += 10
            }
            isDownloading.value = false
        }
    }
}

在Activity中观察ViewModel的状态,自动处理弹窗展示与进度更新:

class MainActivity : AppCompatActivity() {
    private var alertDialog: AlertDialog? = null
    private lateinit var downloadViewModel: DownloadViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
        // 观察下载进度
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                downloadViewModel.downloadProgress.collect { progress ->
                    if (downloadViewModel.isDownloading.value) {
                        showDialogBox(progress)
                    } else {
                        alertDialog?.dismiss()
                    }
                }
            }
        }
        // 启动下载的地方调用downloadViewModel.startDownload()即可
    }

    // onPause时如果要销毁弹窗,也要记得置空变量
    override fun onPause() {
        super.onPause()
        alertDialog?.dismiss()
        alertDialog = null
    }
}

3. 可选优化

如果下载是长时间后台任务,推荐使用WorkManager实现,避免进程被系统杀死后下载中断,同时可以更方便的监听进度。


内容的提问来源于stack exchange,提问作者Harsh Shah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 22:36:04