How is Jetpack Navigation’s Compose support handli...
# compose
z
How is Jetpack Navigation’s Compose support handling `AndroidView`s nested inside composable destinations? I see that
NavBackStackEntryProvider
sets all the owner locals for the destination (
ViewModelStore
,
Lifecycle
,
SavedStateRegistry
, and
SaveableStateRegistry
), and that
AndroidView
manages its view’s hierarchy state, but if a view underneath an
AndroidView
inside a composable destination asks for the
ViewTreeSavedStateRegistryOwner
, for example (and same for the other 2 view tree owners), wouldn’t they skip past the compose nav destination’s owners and find the owner on the android view containing the composition with the nav host? I would expect
AndroidView
to set the view tree owners from the respective composition locals on its child view.
2
FWIW, some CompositionLocals, like
LocalViewModelStoreOwner
don't exist at all anywhere in the androidx.compose code base - they're completely independent things that
AndroidView
wouldn't ever know about
z
Wouldn’t views normally get it through
ViewTreeViewModelStoreOwner
though? And same for
LifecycleOwner
and
SavedStateRegistryOwner
?
i
I'm saying that nothing in androidx.compose knows what
ViewTreeViewModelStoreOwner
should be set to - the composition local is totally unknown to androidx.compose
z
So if you have a structure like this: RootView
ComposeView1
> NavHost > nav destination > AndroidView > ComposeView2 When ComposeView2 reads the 3 view tree owners, it should get the ones defined for that nav destination, right? But because the view tree owners search will only look up the view hierarchy, it will find the same ones read by ComposeView1 (i.e. the ones on RootView). So it won’t get, for example, the right lifecycle events when the destination is navigated away from.
i
No,
ComposeView
will inherit the composition locals
z
Oh, AndroidComposeView is using
provideDefault
isn’t it… (checks…)
i
Using a composition in another composition with an AndroidView in the middle is exactly what those tests I linked to verify
z
Right, i get that works for locals in general. But
AndroidCompositionLocals
looks like it explicitly sets
LocalLifecycleOwner
&
LocalSavedStateRegistryOwner
here – and it gets the values for those locals from the
AndroidComposeView
, which gets them from the view tree here, not the incoming parent composition.
i
Does that happen before or after it applies every composition local from the parent composition?
z
ProvideAndroidCompositionLocals
throws if the
owner.viewTreeOwners
is null, so it would seem like those are read before creating the child composition, and then the composition is created, and then those values are provided before composing the child’s content.
i
As that's what knows about the parent
CompositionContext
, which is really what it should be using as the source of truth I would think?
I guess the problem is then that you really don't know which to trust - the parent composition local or a call to ViewTree somewhere in the interleaving view worlds?
z
Yea, provideDefault wouldn’t work here because it would ignore values set by the intermediate views if it tried to override the ones coming from the parent composition, ie basically just the opposite problem.
I think AndroidView would need to set the view tree owners on the views it manages. That would solve two problems: 1. Any owners specified in the parent composition would be seen by the Android views hosted by that composition. 2. Any child ComposeViews inside those Android views could be reasonably sure that the owners from the view tree are not in conflict with the ones from the parent composition. I think should be feasible for view model and lifecycle owners, but the state registry is tricky because there are already two sources of truth -
LocalSavedStateRegistry
and
LocalSaveableStateRegistry
. I guess
AndroidView
could just use the former for the view tree owner and assume that anyone setting one of those locals would correctly set both of them.
i
No, it isn't feasible for the ViewModel owner, like I said above - the
LocalViewModelStoreOwner
is not visible or available to
AndroidView
z
Ah my bad, I missed that yesterday. So this is only a problem for lifecycle and state registry, great - even simpler.
I tried to summarize my understanding of this thread on the issue I filed about this back in February, might make sense to move the conversation there.
👍 1
👀 1