Skip to content

fix(android): give ComposeView its own Lifecycle to fix #1103 and #1104 - #1105

Open
GaelCO wants to merge 3 commits into
callstack:masterfrom
GaelCO:fix/fix-1103-1104
Open

fix(android): give ComposeView its own Lifecycle to fix #1103 and #1104#1105
GaelCO wants to merge 3 commits into
callstack:masterfrom
GaelCO:fix/fix-1103-1104

Conversation

@GaelCO

Copy link
Copy Markdown

Summary

Fixes#1103
Fixes#1104

Test plan

  • Manually verified with a react-navigation material-top-tabs stack that covering/revealing a screen containing the pager no longer blanks it out.
  • Manually verified a FlatList page inside the pager keeps its scroll position after the screen is covered and revealed again.

…and callstack#1104
react-native-screens fully removes and re-adds a covered screen's Fragment
instead of just hiding it, destroying its view-tree Lifecycle. Compose's
default disposal strategy keys off that ambient Lifecycle, so the pager's
ComposeView was torn down and rebuilt on every cover/reveal cycle, causing
a blank pager (callstack#1103) and loss of page state such as FlatList scroll
position (callstack#1104). Giving the ComposeView its own self-owned Lifecycle lets
the composition survive the cycle untouched.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Android regressions in the Compose-based pager when screens are covered/revealed (notably with react-native-screens) by decoupling the ComposeView’s composition disposal from the ambient Fragment view-tree Lifecycle, keeping the composition (and hosted native page views) alive across cover/reveal cycles.

Changes:

  • Add explicit cleanup in onDropViewInstance to destroy a self-owned Lifecycle and dispose the Compose composition.
  • Rework ComposePagerView to create/bind a ComposeView with a dedicated LifecycleOwner and DisposeOnLifecycleDestroyed strategy.
  • Add an AndroidX Lifecycle runtime dependency required for view-tree lifecycle owner APIs.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
android/src/main/java/com/reactnativepagerview/PagerViewViewManager.ktDisposes pager resources when the RN view instance is dropped.
android/src/main/java/com/reactnativepagerview/ComposePagerView.ktIntroduces a self-owned lifecycle for the ComposeView and adjusts attach/detach behavior to preserve composition across cover/reveal.
android/build.gradleAdds AndroidX Lifecycle runtime dependency for the new lifecycle owner usage.
Suppressed comments (1)

android/src/main/java/com/reactnativepagerview/ComposePagerView.kt:652

  • ComposeViewLifecycleOwner is hard-coded to start in Lifecycle.State.RESUMED and stay there until DESTROYED. That can keep lifecycle-aware work (e.g., coroutines/flows started with lifecycle-aware APIs) running even while the view is detached/covered, which is likely more work than necessary. Consider starting at CREATED and adding explicit attach/detach state transitions so the composition can pause while offscreen without being disposed.
// A Lifecycle that isn't derived from the ambient Fragment/Activity: it
// starts RESUMED and only moves to DESTROYED when destroy() is called
// explicitly, so it survives being covered/revealed by react-native-screens'
// Fragment remove+re-add (see the composeLifecycleOwner field comment on
// ComposePagerView above).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +116 to +120
override fun onDetachedFromWindow() {
updateSameOrientationAncestorsGestureState(false)
if (composeView.parent === this) {
super.removeView(composeView)
didSetContent = false
}
// composeView is intentionally left attached and alive here: its
// Lifecycle is self-owned (see composeLifecycleOwner) and only reaches
// DESTROYED in dispose(), so there is nothing to tear down on a mere
Comment threadandroid/build.gradle Outdated
Comment on lines +249 to +251
// Needed for ComposeViewLifecycleOwner (see ComposePagerView.kt), which
// gives the ComposeView a self-owned Lifecycle instead of the ambient one.
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1"

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants

@GaelCO