Android中DialogActivity执行onDestroy后仍驻留后台的解决求助
问题描述
我正在开发一款每10秒询问用户当前行为的应用,为此创建了用于弹出多选对话框的DialogActivity,以及触发它的Worker和MainActivity代码(代码见下方)。
问题:点击对话框的OK/取消按钮后,对话框消失,但DialogActivity仍驻留在后台可重新打开,且已确认onDestroy方法已被调用。设备为基于Android 12的MIUI 14.0.1,求彻底销毁该Activity的方法。
DialogActivity代码
import android.app.AlertDialog import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import androidx.work.OneTimeWorkRequest import androidx.work.WorkManager import java.util.concurrent.TimeUnit class DialogActivity : AppCompatActivity() { override fun onStop() { super.onStop() Log.d("DialogActivity", "onStop") // Votre code personnalisé ici } override fun onDestroy() { super.onDestroy() Log.d("DialogActivity", "onDestroy") } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val builder = AlertDialog.Builder(this) builder.setTitle("Que fais-tu ?") val items = arrayOf("Activité 1", "Activité 2", "Activité 3") val checkedItems = BooleanArray(items.size) { false } builder.setMultiChoiceItems(items, checkedItems) { _, which, isChecked -> checkedItems[which] = isChecked } builder.setPositiveButton("OK") { _, _ -> val selectedItems = items.filterIndexed { index, _ -> checkedItems[index] } Log.d("DialogActivity", "L'utilisateur a sélectionné : $selectedItems") //planNextWorker() finishAffinity() } builder.setNegativeButton("Annuler") { dialog, _ -> dialog.cancel() //planNextWorker() finishAffinity() } builder.setOnCancelListener { //planNextWorker() finishAffinity() } // Afficher le dialogue APRÈS avoir défini tous les écouteurs et les boutons. builder.show() } private fun planNextWorker() { val followUpRequest = OneTimeWorkRequest.Builder(UserActivityAskingWorker::class.java) .setInitialDelay(10, TimeUnit.SECONDS) .build() WorkManager.getInstance(this).enqueue(followUpRequest) } }
MainActivity及Worker代码
package com.treehousetutorial.controll_app_0_2 import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle import android.provider.Settings import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.work.OneTimeWorkRequest import androidx.work.WorkManager import androidx.work.Worker import androidx.work.WorkerParameters import com.treehousetutorial.controll_app_0_2.ui.theme.Controll_app_0_2Theme import java.util.concurrent.TimeUnit class MainActivity : ComponentActivity() { private val overlayPermissionLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { // Gérez le résultat ici si nécessaire } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Demander la permission SYSTEM_ALERT_WINDOW if (!Settings.canDrawOverlays(this)) { val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:$packageName")) overlayPermissionLauncher.launch(intent) } setContent { Controll_app_0_2Theme { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { Greeting("Android") } } } // Commencer le Worker startOneTimeWork() } private fun startOneTimeWork() { val oneTimeRequest = OneTimeWorkRequest.Builder(UserActivityAskingWorker::class.java) .setInitialDelay(10, TimeUnit.SECONDS) .build() WorkManager.getInstance(this).enqueue(oneTimeRequest) } companion object { const val OVERLAY_PERMISSION_REQ_CODE = 1001 } } @Composable fun Greeting(name: String, modifier: Modifier = Modifier) { Text( text = "Hello $name!", modifier = modifier ) } @Preview(showBackground = true) @Composable fun GreetingPreview() { Controll_app_0_2Theme { Greeting("Android") } } class UserActivityAskingWorker(appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) { override fun doWork(): Result { val intent = Intent(applicationContext, DialogActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK) applicationContext.startActivity(intent) return Result.success() } }
解决方案
针对MIUI系统的定制化任务栈管理逻辑,可尝试以下几种方法彻底销毁DialogActivity:
1. 替换finishAffinity()为finishAndRemoveTask()
finishAffinity()仅结束当前任务栈内有亲缘关系的Activity,但MIUI可能仍保留任务栈记录。finishAndRemoveTask()会直接将整个任务栈从系统最近任务列表中移除:
// OK按钮点击事件 builder.setPositiveButton("OK") { _, _ -> val selectedItems = items.filterIndexed { index, _ -> checkedItems[index] } Log.d("DialogActivity", "L'utilisateur a sélectionné : $selectedItems") //planNextWorker() finishAndRemoveTask() } // 取消按钮点击事件 builder.setNegativeButton("Annuler") { dialog, _ -> dialog.cancel() //planNextWorker() finishAndRemoveTask() } // 对话框取消监听 builder.setOnCancelListener { //planNextWorker() finishAndRemoveTask() }
2. 在Manifest中配置Activity的历史记录属性
给DialogActivity添加android:noHistory="true"和android:excludeFromRecents="true"属性,确保Activity退出后不会留在历史栈和最近任务列表中:
<activity android:name=".DialogActivity" android:noHistory="true" android:excludeFromRecents="true" />
3. 启动Activity时添加FLAG_ACTIVITY_NO_HISTORY标记
在Worker启动DialogActivity时,添加该标记让Activity不会被加入任务栈历史:
class UserActivityAskingWorker(appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) { override fun doWork(): Result { val intent = Intent(applicationContext, DialogActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK or Intent.FLAG_ACTIVITY_NO_HISTORY) applicationContext.startActivity(intent) return Result.success() } }
4. 组合调用多种销毁方法
如果单一方法无效,可组合调用确保彻底清理:
builder.setPositiveButton("OK") { _, _ -> val selectedItems = items.filterIndexed { index, _ -> checkedItems[index] } Log.d("DialogActivity", "L'utilisateur a sélectionné : $selectedItems") //planNextWorker() finish() finishAffinity() finishAndRemoveTask() }
优先尝试方法1和方法2的组合,这是针对MIUI系统最有效的解决方案。
内容的提问来源于stack exchange,提问作者Brinax
相关产品推荐
相关产品推荐

