java.lang.IllegalArgumentException: View not attached to window manager

本文解析了Android中View未附加到WindowManager错误的原因,通常发生在试图销毁已重启Activity的Dialog时。文章详细解释了Dialog的生命周期管理,并提供了两种解决方案:使用Activity自带的Dialog控制方法或限制Dialog的生命周期。
转载自 http://www.tuicool.com/articles/aMNN3y
AndroidRuntime: FATAL EXCEPTION: main
AndroidRuntime: java.lang.IllegalArgumentException: View not attached to window manager
AndroidRuntime: 	at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:385)
AndroidRuntime: 	at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:287)
AndroidRuntime: 	at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:79)
AndroidRuntime: 	at android.app.Dialog.dismissDialog(Dialog.java:323)
AndroidRuntime: 	at android.app.Dialog.dismiss(Dialog.java:306)
AndroidRuntime: 	at com.android.stk.StkDialogActivity$4.onClick(StkDialogActivity.java:188)
AndroidRuntime: 	at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:169)
AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:99)
AndroidRuntime: 	at android.os.Looper.loop(Looper.java:153)
AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:5299)
AndroidRuntime: 	at java.lang.reflect.Method.invokeNative(Native Method)
AndroidRuntime: 	at java.lang.reflect.Method.invoke(Method.java:511)
AndroidRuntime: 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
AndroidRuntime: 	at dalvik.system.NativeStart.main(Native Method)

为什么会报View not attached to window manager错误?

        这个错误的意思是说我们所操作的View没有被纳入window manager的管理。
        我们知道所有的窗口创建和管理都是依附于window manager的,因此Dialog的创建也不例外。Dialog的创建流程通过查看源码可以知道,在Dialog的构造函数中,创建了一个Window对象,但我们知道Window对象并不是用于显示的,真正用于显示的是View对象。因此通过Dialog的show方法构造了一个mDecor的View对象,并最终通过WindowManager的addView()方法显示Dialog。
        通过查看log信息我们可以看到com.android.stk.StkDialogActivity$4.onClick(StkDialogActivity.java:188)
查看对应的StkDialogActivity代码后发现,在188行处代码为dialog.dismiss();
        在网络上搜索后发现,多数情况下出现这种错误,都是在dismiss Dialog时,发现创建该Dialog的Activity存在而导致的。
比如在界面上显示一个Dialog,当任务处理结束后再Dismiss Dialog。如果在Dialog显示期间,该Activity因为某种原因被杀掉且又重新启动了,那么当任务结束时,Dismiss Dialog的时候WindowManager检查,就会发现该Dialog所属的Activity已经不存在了(重新启动了一次,是一个新的Activity),所以会报IllegalArgumentException: View not attached to window manager.
通过以上分析我们可以知道在STK Dialog在执行dismiss方法时,发现启动它的Activity已经不见了,被杀掉了(现在这个是重新启动的),所以才报错出现异常。

Activity被杀掉时,Dialog存在么?

        可能大家会有疑问,Dialog都没有看到,就出现错误了,怎么能确定该Dialog当时一定是显示的呢?继续在log中搜索我们可以发现:
WindowManager: Activity com.android.stk.StkDialogActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{41fea228 V.E..... R.....ID 0,0-1026,433} that was originally added here
WindowManager: android.view.WindowLeaked: Activity com.android.stk.StkDialogActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{41fea228 V.E..... R.....ID 0,0-1026,433} that was originally added here
WindowManager: 	at android.view.ViewRootImpl.<init>(ViewRootImpl.java:409)
WindowManager: 	at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:218)
WindowManager: 	at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
WindowManager: 	at android.app.Dialog.show(Dialog.java:281)
WindowManager: 	at android.app.AlertDialog$Builder.show(AlertDialog.java:951)
WindowManager: 	at com.android.stk.StkDialogActivity.onCreate(StkDialogActivity.java:192)
WindowManager: 	at android.app.Activity.performCreate(Activity.java:5122)
WindowManager: 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1081)
WindowManager: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270)
WindowManager: 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2358)
WindowManager: 	at android.app.ActivityThread.access$600(ActivityThread.java:156)
WindowManager: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1340)
WindowManager: 	at android.os.Handler.dispatchMessage(Handler.java:99)
WindowManager: 	at android.os.Looper.loop(Looper.java:153)
WindowManager: 	at android.app.ActivityThread.main(ActivityThread.java:5299)
WindowManager: 	at java.lang.reflect.Method.invokeNative(Native Method)
WindowManager: 	at java.lang.reflect.Method.invoke(Method.java:511)
WindowManager: 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
WindowManager: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
WindowManager: 	at dalvik.system.NativeStart.main(Native Method)
        这里的WindowManager报错是什么意思呢? 这段log是WindowManager抛出的error错误,当我们的Dialog还没有dismiss时,如果此时该Activity被销毁了,那么就会出现以上错误,提示窗口泄漏(leaked window)。这里自己也做了一个实验,写一个demo,在Activity的onCreate方法中显示一个Dialog,然后直接调用finish方法。代码大致如下:
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        AlertDialog.Builder info = new Builder(this);
        info.setTitle("Dialog").setPositiveButton("OK", null).setMessage("This is a Dialog");;
        info.show(); 
        finish();
    }
        直接将此程序run到模拟器或者真机上,查看log我们就能看到leaked window的报错信息。因此这也证明了前面我们的假设,即StkActivity在被销毁时,其所依附的Dialog是存在的。 

如何解决这个问题呢?

        通过以上分析之后我们知道了问题出现的原因,那么如何解决呢?可以通过以下两个方面来解决:
1. 使用Activity自带的Dialog控制方法
        在Activity中需要使用对话框,可以使用Activity自带的回调,比如onCreateDialog(),showDialog(),dimissDialog(),removeDialog()等等。毕竟这些都是Activity自带的方法,所以用起来更方便,也不用显示创建和操控Dialog对象,一切都由框架操控,相对来说比较安全。
2. 限制Dialog的生命周期
        让创建的Dialog对象的存活周期跟Activity的生命周期一致,也就是说Dialog的生命周期被限定在Activity的onCreate()和onDestroy()方法之间。


2025-07-31 18:31:004,tiny-log,[1753957864341], [main]app crash: java.lang.RuntimeException: Unable to resume activity {com.mercusys.halo/com.tplink.mercusys.component.dashboard.view.MainActivity}: java.lang.IllegalArgumentException: View=com.android.internal.policy.DecorView{fc3d391 V.ED..... R.....ID 0,0-1024,651}[SystemTimeMerActivity] not attached to window manager at android.app.ActivityThread.performResumeActivity(ActivityThread.java:5467) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:5500) at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:73) at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:63) at android.app.servertransaction.TransactionExecutor.executeLifecycleItem(TransactionExecutor.java:169) at android.app.servertransaction.TransactionExecutor.executeTransactionItems(TransactionExecutor.java:101) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:80) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2773) at android.os.Handler.dispatchMessage(Handler.java:109) at android.os.Looper.loopOnce(Looper.java:232) at android.os.Looper.loop(Looper.java:317) at android.app.ActivityThread.main(ActivityThread.java:8934) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:591) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911) Caused by: java.lang.IllegalArgumentException: View=com.android.internal.policy.DecorView{fc3d391 V.ED..... R.....ID 0,0-1024,651}[SystemTimeMerActivity] not attached to window manager at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:587) at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:494) at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:216) at android.app.Dialog.dismissDialog(Dialog.java:404) at android.app.Dialog.dismiss(Dialog.java:386) at androidx.appcompat.app.AppCompatDialog.dismiss(AppCompatDialog.java:1) at com.tplink.mercusys.component.core.lifecycle.r0.onUnregister(MeshNetworkConnectionObserver.java:21) at com.tplink.mercusys.base.lifecycle.ApplicationStateReceiverDelegate.registerMeshConnectObserver(ApplicationStateReceiverDelegate.java:15) at com.tplink.mercusys.base.lifecycle.ApplicationStateReceiverDelegate.registerMeshNetworkObserver(ApplicationStateReceiverDelegate.java:1) at com.tplink.mercusys.component.dashboard.viewmodel.BaseDashboardViewModel.x6(BaseDashboardViewModel.java:15) at com.tplink.mercusys.component.dashboard.view.NetworkTabFragment.Bg(NetworkTabFragment.java:89) at com.tplink.mercusys.component.dashboard.view.NetworkTabFragment.Ve(NetworkTabFragment.java:54) at com.tplink.apps.architecture.BaseMvvmFragment.onViewCreated(BaseMvvmFragment.kt:45) at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:5) at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:272) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:125) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:231) at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:82) at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:22) at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:39) at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2) at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:10) at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:272) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:125) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:231) at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:82) at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:22) at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:39) at androidx.fragment.app.FragmentManager.dispatchResume(FragmentManager.java:12) at androidx.fragment.app.FragmentController.dispatchResume(FragmentController.java:5) at androidx.fragment.app.FragmentActivity.onResumeFragments(FragmentActivity.java:10) at androidx.fragment.app.FragmentActivity.onPostResume(FragmentActivity.java:4) at androidx.appcompat.app.AppCompatActivity.onPostResume(AppCompatActivity.java:1) at android.app.Activity.performResume(Activity.java:9266) at android.app.ActivityThread.performResumeActivity(ActivityThread.java:5457) ... 14 more 崩溃分析
08-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值