Skip to content

Fix in-app message flickering with Jetpack Compose#1025

Closed
franco-zalamena-iterable wants to merge 1 commit into
masterfrom
fix/461-compose-compatibility-flickering
Closed

Fix in-app message flickering with Jetpack Compose#1025
franco-zalamena-iterable wants to merge 1 commit into
masterfrom
fix/461-compose-compatibility-flickering

Conversation

@franco-zalamena-iterable
Copy link
Copy Markdown
Contributor

@franco-zalamena-iterable franco-zalamena-iterable commented Apr 7, 2026

Summary

  • Fix in-app message dialog flickering when used with Jetpack Compose
  • Stabilize dialog window and WebView rendering

Test plan

  • Test in-app messages in a Compose-based app
  • Verify no flickering
  • Verify in-app messages still work in traditional View-based apps

🤖 Generated with Claude Code

Stabilize the dialog fragment rendering to prevent visual flickering
when used in Jetpack Compose apps. The fixes address three root causes:

1. Disable default window animations on the dialog - these conflict
   with Compose's recomposition cycle, causing visual artifacts. The SDK
   already handles animations manually via showAndAnimateWebView().

2. Enable hardware layer rendering on the WebView - this prevents the
   WebView from being re-rendered during Compose layout passes.

3. Remove redundant layout invalidation calls - applyWindowGravity was
   called three times (onCreateDialog, onCreateView, onStart) and
   requestLayout() was called explicitly after setLayoutParams() which
   already triggers a layout pass. These redundant calls cause layout
   thrashing that manifests as flickering in Compose environments.

Fixes #461

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@franco-zalamena-iterable
Copy link
Copy Markdown
Contributor Author

PR Analysis

Problem: In-app message dialogs flicker (visual artifacts) when displayed in a Jetpack Compose-based app. Compose's recomposition cycle re-triggers lifecycle callbacks and layout passes on the DialogFragment, causing redundant window updates that manifest as flickering.

Ideal fix plan:

  • Identify which lifecycle callbacks or layout operations are being re-triggered by Compose recomposition
  • Consolidate window gravity setup to a single point (onCreateDialog) instead of repeating it in onStart, onCreateView, and onCreateDialog
  • Disable default dialog window animations that conflict with the custom animation system already in place (showAndAnimateWebView)
  • Remove redundant requestLayout() calls in the resize() method since setLayoutParams() already triggers a layout pass internally
  • Consider hardware-accelerated rendering for the WebView to prevent visual artifacts during Compose layout passes
  • Verify the fix works for all in-app layouts (TOP, BOTTOM, CENTER, FULLSCREEN) and does not regress View-based apps

What the PR did:

  • Removed applyWindowGravity() call from onStart() (was redundant with onCreateDialog)
  • Removed applyWindowGravity() call from onCreateView() (was redundant with onCreateDialog)
  • Added window.setWindowAnimations(0) in onCreateDialog to disable default dialog animations
  • Set LAYER_TYPE_HARDWARE on the WebView
  • Removed explicit requestLayout() calls in the resize() method

Assessment:

  • Root cause identified: partially -- the PR correctly identifies that redundant lifecycle calls and layout passes are the triggers, but the comments frame Compose "recomposition" as the cause rather than the real mechanism: Compose re-triggering Fragment lifecycle callbacks (onStart) when state changes cause the ComposeView hosting the Fragment to recompose. The distinction matters for understanding when this would occur.
  • Fix correctness: partially correct -- consolidating gravity to onCreateDialog and removing redundant requestLayout() calls are sound changes. However, setWindowAnimations(0) disables ALL dialog window enter/exit transitions globally, which may cause the dialog to appear/disappear abruptly on View-based apps where the custom animation timing (400ms postOnAnimationDelayed in hideWebView) was calibrated against the default window animation. The hardware layer type on WebView is a reasonable stabilization measure but adds GPU memory cost; it would be better to confirm it actually addresses a specific symptom rather than being applied speculatively.
  • Missed:
    • No check on whether disabling window animations regresses the dismiss experience (hideWebView relies on a 400ms delay that was presumably tuned with default window animations active)
    • The showAndAnimateWebView() comment says "we handle animations manually" but the exit path in hideWebView() also depends on timing that may shift without window animations
    • No investigation into whether ComposeView or AndroidViewBinding is wrapping the fragment and whether setRecompositionMode or other Compose-side mitigations could address this at the integration layer
  • Wrong assessment: the comments suggest "Compose's recomposition cycle can conflict with the window animation system" -- this is imprecise. Compose recomposition does not directly touch the window animation system. The conflict is that recomposition can re-trigger Fragment lifecycle methods (specifically onStart when the dialog's host is recomposed), and those methods were doing redundant layout work. The window animation disabling is a separate fix for a potentially separate symptom.
  • Tests: needed but missing -- at minimum, a unit test verifying that applyWindowGravity is called exactly once (in onCreateDialog) and not in onStart/onCreateView would prevent regressions. An instrumented test with a Compose host would be ideal but admittedly harder.

@franco-zalamena-iterable franco-zalamena-iterable deleted the fix/461-compose-compatibility-flickering branch April 8, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant