{"record":{"id":"1d1273c706281bfe","repo":"Tencent/QMUI_Android","slug":"you-should-config-the-exposure-on-parent-parent","errorCode":null,"errorMessage":"You should config the exposure on parent($parent) for constraint effect.","messagePattern":"You should config the exposure on parent\\(\\$parent\\) for constraint effect\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"qmui/src/main/java/com/qmuiteam/qmui/exposure/ExposureEffect.kt","lineNumber":40,"sourceCode":"        target: View,\n        container: ViewGroup,\n        data: Exposure\n    ){\n\n    }\n}\n\nclass ParentExposedRequestExposureEffect(val parent: ViewGroup) : ExposureEffect {\n    override fun doBeforeExpose(\n        target: View,\n        container: ViewGroup,\n        exposure: Exposure,\n        lastExposure: Exposure?,\n        type: ExposureType\n    ): EffectResult {\n        val isParentConfigSet = parent.getTag(R.id.qmui_exposure_config) as? Boolean ?: false\n        if (!isParentConfigSet) {\n            throw RuntimeException(\"You should config the exposure on parent($parent) for constraint effect.\")\n        }\n        val holder = parent.getTag(R.id.qmui_exposure_holder) as? Runnable\n        if (holder != null) {\n            parent.removeCallbacks(holder)\n            parent.setTag(R.id.qmui_exposure_holder, null)\n            holder.run()\n        }\n        return if(parent.isInExposure()) EffectResult.pass else EffectResult.unHandled\n    }\n}\n\n\nclass RecyclerExposureEffect(\n    val parent: ViewGroup,\n    val safeDuration: Long = 500,\n    val zombieDuration: Long = 2000\n) : ExposureEffect {\n","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/Tencent/QMUI_Android/blob/026e7d486677d6593a96689cd590ec3561176717/qmui/src/main/java/com/qmuiteam/qmui/exposure/ExposureEffect.kt#L22-L58","documentation":"ExposureEffect's constrained exposure logic requires the parent view to have been set up via the library's exposure config call, which stores a Boolean in R.id.qmui_exposure_config. If that tag is missing/false when doBeforeExpose runs for a constraint-type exposure, a RuntimeException is thrown telling you to configure exposure on the parent.","triggerScenarios":"Using constraint-based exposure on a child view without first calling the exposure config/setup API on its direct parent view, so the qmui_exposure_config tag is unset.","commonSituations":"Adding exposure tracking to a child inside a container but only configuring the child; restructuring view hierarchies so the configured parent is no longer the direct parent; forgetting setup after refactor.","solutions":["Call the library's exposure config (e.g. ExposureEffect setup/config extension) on the direct parent view before enabling constraint exposure on the child.","Verify parent.getTag(R.id.qmui_exposure_config) is true at the time of exposure.","Re-apply the config after view hierarchy changes or adapter rebinds."],"exampleFix":"// before\nchildView.exposure() // constraint effect, parent not configured -> throws\n// after\nparentView.configExposure() // sets qmui_exposure_config tag\nchildView.exposure()","handlingStrategy":"validation","validationCode":"check(parent.getTag(R.id.qmui_exposure_config) == true) { \"configure exposure on parent before constraint effect\" }","typeGuard":"fun ViewGroup.hasExposureConfig(): Boolean = getTag(R.id.qmui_exposure_config) as? Boolean == true","tryCatchPattern":"try { childView.exposure() } catch (e: RuntimeException) { parentView.configExposure(); childView.exposure() }","preventionTips":["Always call the exposure config on the direct parent before child constraint exposure","Re-apply config after rebinding/restructuring views","Keep setup and usage in the same custom view/component"],"tags":["android","ui","exposure-tracking","view-tags","config"],"backgroundTag":"missing-required-config","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"}