{"record":{"id":"68a3a6af9f729d80","repo":"Tencent/QMUI_Android","slug":"view-is-not-attached-to-window","errorCode":null,"errorMessage":"View is not attached to window","messagePattern":"View is not attached to window","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"compose/src/main/java/com/qmuiteam/compose/modal/QMUIModal.kt","lineNumber":126,"sourceCode":"        val activity = contentLayout.context as? AppCompatActivity ?: throw RuntimeException(\"view's rootView's context is not AppCompatActivity\")\n        return contentLayout to activity.onBackPressedDispatcher\n    }\n}\n\nval DefaultModalHostProvider = ActivityHostModalProvider()\n\nfun View.qmuiModal(\n    mask: Color = DefaultMaskColor,\n    systemCancellable: Boolean = true,\n    maskTouchBehavior: MaskTouchBehavior = MaskTouchBehavior.dismiss,\n    uniqueId: Long = SystemClock.elapsedRealtimeNanos(),\n    modalHostProvider: ModalHostProvider = DefaultModalHostProvider,\n    enter: EnterTransition = fadeIn(tween(), 0f),\n    exit: ExitTransition = fadeOut(tween(), 0f),\n    content: @Composable AnimatedVisibilityScope.(QMUIModal) -> Unit\n): QMUIModal {\n    if (!isAttachedToWindow) {\n        throw RuntimeException(\"View is not attached to window\")\n    }\n    val modalHost = modalHostProvider.provide(this)\n    val modal = AnimateModalImpl(\n        modalHost.first,\n        modalHost.second,\n        mask,\n        systemCancellable,\n        maskTouchBehavior,\n        enter,\n        exit,\n        content\n    )\n    val hostView = modalHost.first\n    handleModelUnique(hostView, modal, uniqueId)\n    return modal\n}\n\nfun View.qmuiStillModal(","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/Tencent/QMUI_Android/blob/026e7d486677d6593a96689cd590ec3561176717/compose/src/main/java/com/qmuiteam/compose/modal/QMUIModal.kt#L108-L144","documentation":"qmuiModal checks this View.isAttachedToWindow before resolving the modal host. If the view is not currently attached to a window, showing a modal is impossible (no root view / content parent exists), so a RuntimeException is thrown. Called by qmuiBottomSheet, qmuiDialog, and qmuiToast.","triggerScenarios":"Calling qmuiModal/qmuiBottomSheet/qmuiDialog/qmuiToast on a view before it is attached (e.g. in onCreate before the view is in the hierarchy) or after it is detached (after onDestroy/RecyclerView recycling).","commonSituations":"Showing a dialog in Activity.onCreate() without waiting for attach; calling from a detached RecyclerView item view; showing a toast/dialog after configuration change removed the old view.","solutions":["Defer the call until the view is attached: view.doOnAttach { ... } or view.post { ... }.","Show the modal from an Activity/Fragment lifecycle-safe point (onResume / onViewCreated with attach confirmed).","Guard with a check before calling and skip/retry if not attached."],"exampleFix":"// before\nrootView.qmuiDialog { ... } // throws if called in onCreate\n// after\nrootView.doOnAttach { it.qmuiDialog { ... } }","handlingStrategy":"validation","validationCode":"if (!view.isAttachedToWindow) { view.doOnAttach { show() } } else { show() }","typeGuard":"val View.canShowModal: Boolean get() = isAttachedToWindow","tryCatchPattern":"try { view.qmuiModal { ... } } catch (e: RuntimeException) { pendingShow = true }","preventionTips":["Call modal APIs after the view is attached (doOnAttach/onResume)","Never call from onDestroy or recycled item views","Queue the show request until attach completes"],"tags":["android","ui","modal","view-attachment","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"026e7d486677d6593a96689cd590ec3561176717","analyzedAt":"2026-09-06T13:32:24.816Z","contentChangedAt":"2026-09-06T13:32:24.816Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}