Tencent/QMUI_Android · error · RuntimeException

view's rootView's context is not AppCompatActivity

Error message

view's rootView's context is not AppCompatActivity

What it means

After finding the android.R.id.content FrameLayout, provide() casts its context to AppCompatActivity. If the context is not an AppCompatActivity (different Activity base class, Service, Application, or wrapped ContextThemeWrapper), the safe cast fails and a RuntimeException is thrown because OnBackPressedDispatcher is read from AppCompatActivity.

Source

Thrown at compose/src/main/java/com/qmuiteam/compose/modal/QMUIModal.kt:108

    fun doOnShow(listener: Action): QMUIModal
    fun doOnDismiss(listener: Action): QMUIModal
    fun removeOnShowAction(listener: Action): QMUIModal
    fun removeOnDismissAction(listener: Action): QMUIModal

    fun interface Action {
        fun invoke(modal: QMUIModal)
    }
}

fun interface ModalHostProvider {
    fun provide(view: View): Pair<FrameLayout, OnBackPressedDispatcher>
}

class ActivityHostModalProvider : ModalHostProvider {
    override fun provide(view: View): Pair<FrameLayout, OnBackPressedDispatcher> {
        val contentLayout =
            view.rootView.findViewById<FrameLayout>(Window.ID_ANDROID_CONTENT) ?: throw RuntimeException("View is not attached to Activity")
        val activity = contentLayout.context as? AppCompatActivity ?: throw RuntimeException("view's rootView's context is not AppCompatActivity")
        return contentLayout to activity.onBackPressedDispatcher
    }
}

val DefaultModalHostProvider = ActivityHostModalProvider()

fun View.qmuiModal(
    mask: Color = DefaultMaskColor,
    systemCancellable: Boolean = true,
    maskTouchBehavior: MaskTouchBehavior = MaskTouchBehavior.dismiss,
    uniqueId: Long = SystemClock.elapsedRealtimeNanos(),
    modalHostProvider: ModalHostProvider = DefaultModalHostProvider,
    enter: EnterTransition = fadeIn(tween(), 0f),
    exit: ExitTransition = fadeOut(tween(), 0f),
    content: @Composable AnimatedVisibilityScope.(QMUIModal) -> Unit
): QMUIModal {
    if (!isAttachedToWindow) {
        throw RuntimeException("View is not attached to window")

View on GitHub (pinned to 026e7d4866)

Solutions

  1. Make the hosting Activity extend androidx.appcompat.app.AppCompatActivity.
  2. Unwrap ContextThemeWrapper chains in a custom ModalHostProvider to find the underlying Activity.
  3. Implement ModalHostProvider yourself returning contentLayout and the dispatcher from whatever Activity type you use.
  4. Check the Activity base class before invoking the modal API.

Example fix

// before
class MainActivity : ComponentActivity() { ... } // throws in provide()
// after
class MainActivity : AppCompatActivity() { ... }
Defensive patterns

Strategy: type-guard

Validate before calling

fun requiresAppCompat(view: View): Boolean {
  val ctx = view.context
  return ctx is AppCompatActivity || (ctx is ContextWrapper && ctx.baseContext is AppCompatActivity)
}

Type guard

fun View.appCompatActivity(): AppCompatActivity? =
  generateSequence(context as? ContextWrapper) { it.baseContext as? ContextWrapper }
    .filterIsInstance<AppCompatActivity>().firstOrNull()

Try / catch

try { view.qmuiBottomSheet { ... } } catch (e: RuntimeException) { fallbackToPlainDialog() }

Prevention

When it happens

Trigger: Calling a qmui modal API with a view whose Activity host extends Activity/AppCompatActivity-like other base (e.g. ComponentActivity, FragmentActivity) or whose content view's context is wrapped or non-Activity.

Common situations: App migrated to ComponentActivity/FragmentActivity while QMUI requires AppCompatActivity; using ApplicationContext-inflated views; theme-wrapped contexts that break the direct cast.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of Tencent/QMUI_Android@026e7d4866 (2026-09-06). Data as JSON: /api/errors/8962181e81f10118. Report an issue: GitHub.