android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an appl

本文讲述了在使用AlertDialog时的一个常见错误,即在实例化时错误地使用了getApplicationContext作为上下文。正确的做法是使用当前Activity的上下文,例如SearchActivity.this。这是因为AlertDialog依赖于Activity的生命周期。

今天使用AlertDialog的时候发现一个坑,在实例化AlertDialog时参数传入getApplicationContext,报了如下的错:


在new AlertDialog(context)时,context只能传入该activity的context,而不能传入getApplicationContext()的context,也就是

AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());
这样的写法是错的,正确的写法应该是:

 AlertDialog.Builder builder = new AlertDialog.Builder(SearchActivity.this);
我的理解是,getApplicationContext获取到的context是应用程序的context,当这个activity销毁了它还存在,而AlertDialog是属于一个Activity的,当Activity销毁时它也随之销毁,所以传入的context只能是activity的context,也就是Activity.this。


`android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?` 错误通常是由于在创建弹窗时使用了无效的上下文或上下文的生命周期问题导致的。以下是一些解决该问题的方法: #### 使用 Activity 上下文而非 Application 上下文 在创建弹窗时,不能使用 `getApplicationContext()`,因为应用程序上下文没有窗口令牌,弹窗需要依赖于 Activity 上下文。例如,将 `AlertDialog` 或 `ProgressDialog` 的上下文从 `getApplicationContext()` 改为 `Activity` 实例: ```java // 错误示例 new AlertDialog.Builder(getApplicationContext()) .setIcon(android.R.drawable.ic_dialog_alert) .setTitle("Warnning") .setPositiveButton("Yes", positiveListener) .setNegativeButton( "No", negativeListener) .create().show(); // 正确示例 new AlertDialog.Builder(YourActivity.this) .setIcon(android.R.drawable.ic_dialog_alert) .setTitle("Warnning") .setPositiveButton("Yes", positiveListener) .setNegativeButton( "No", negativeListener) .create().show(); ``` #### 确保 Activity 处于活动状态 在显示弹窗之前,要确保 Activity 是处于活动状态(如 `onResume()` 之后)。可以在 `onWindowFocusChanged` 或 `onResume` 等方法中显示弹窗: ```java @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus && !isMainPopupShowing) { PopupWindowGroup.getInstance(YourActivity.this).showMainPopup(); isMainPopupShowing = true; } } ``` #### 检查 Service 中显示弹窗的方式 如果在 Service 中显示弹窗,要使用 `WindowManager` 并确保权限正确。如在 Service 中显示 Compose 弹窗的示例: ```kotlin import android.annotation.SuppressLint import android.app.Service import android.content.Intent import android.graphics.PixelFormat import android.os.Build import android.os.IBinder import android.view.Gravity import android.view.LayoutInflater import android.view.WindowManager import androidx.compose.ui.platform.ComposeView import androidx.compose.material.Text import androidx.compose.runtime.Composable class PopupService : Service() { private lateinit var windowManager: WindowManager private lateinit var composeView: ComposeView override fun onCreate() { super.onCreate() windowManager = getSystemService(WINDOW_SERVICE) as WindowManager composeView = ComposeView(this).apply { setContent { PopupContent() } } } @SuppressLint("InflateParams") override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { val layoutParams = WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY } else { WindowManager.LayoutParams.TYPE_PHONE }, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT ).apply { gravity = Gravity.TOP or Gravity.START } windowManager.addView(composeView, layoutParams) return START_STICKY } override fun onDestroy() { super.onDestroy() windowManager.removeView(composeView) } override fun onBind(intent: Intent?): IBinder? { return null } } @Composable fun PopupContent() { Text(text = "这是一个 Compose 弹窗") } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值