Android navigation providers like fragments, jetpack nav, and this one are expected to provide Lifecycles to their child content that represents the lifecycle of their navigation frame, and saved state registries (the android SavedStateRegistry and the compose SaveableStateRegistry) that will save and restore state. This library currently only satisfies ⅓ of that contract - it provides the compose state registry, via the composition local LocalSaveableStateRegistry. However, it is not enough to also provide LocalLifecycle and LocalSavedStateRegistry - those work for composable, but not Android Views. Android views, in particular ComposeView, access these things via the methods on the ViewTree*Owners classes. These methods search up the view tree hierarchy. So navigation providers need to ensure that the LifecycleOwner and SavedStateRegistryOwner are set somewhere in the view tree for each navigation frame. As far as I can tell, even jetpack nav does not handle this case.
One way to do this would be for the compose mechanism for hosting android views inside compositions, AndroidView, to read the aforementioned composition locals and set the view tree owners to the same values on the view it manages. Unfortunately, as of the time of writing, it does not do this. I have filed an issue about it, but it’s not clear the compose team agrees this is a valid responsibility.
Another, much hackier way to solve this is for the navigation provider to insert and android view at the root of each child’s content, set the view tree owners on there, then host the child composable content inside that view. This would ensure that any child Android views in that content would find the owners on that android view when searching up the view tree, at the cost of having an otherwise entirely useless view in the middle of what might otherwise be pure composable content. However, this hack would be entirely transparent to users of this library, at least in terms of api.
This might require changing the FrameController API to deal in composable wrapper functions instead of modifiers.
Android navigation providers like fragments, jetpack nav, and this one are expected to provide
Lifecycles to their child content that represents the lifecycle of their navigation frame, and saved state registries (the androidSavedStateRegistryand the composeSaveableStateRegistry) that will save and restore state. This library currently only satisfies ⅓ of that contract - it provides the compose state registry, via the composition localLocalSaveableStateRegistry. However, it is not enough to also provideLocalLifecycleandLocalSavedStateRegistry- those work for composable, but not Android Views. Android views, in particularComposeView, access these things via the methods on theViewTree*Ownersclasses. These methods search up the view tree hierarchy. So navigation providers need to ensure that theLifecycleOwnerandSavedStateRegistryOwnerare set somewhere in the view tree for each navigation frame. As far as I can tell, even jetpack nav does not handle this case.One way to do this would be for the compose mechanism for hosting android views inside compositions,
AndroidView, to read the aforementioned composition locals and set the view tree owners to the same values on the view it manages. Unfortunately, as of the time of writing, it does not do this. I have filed an issue about it, but it’s not clear the compose team agrees this is a valid responsibility.Another, much hackier way to solve this is for the navigation provider to insert and android view at the root of each child’s content, set the view tree owners on there, then host the child composable content inside that view. This would ensure that any child Android views in that content would find the owners on that android view when searching up the view tree, at the cost of having an otherwise entirely useless view in the middle of what might otherwise be pure composable content. However, this hack would be entirely transparent to users of this library, at least in terms of api.
This might require changing the
FrameControllerAPI to deal in composable wrapper functions instead of modifiers.