Fix IllegalStateException: No ViewModelStoreOwner was provided via LocalViewModelStoreOwner in CompatComposeView#2912
Conversation
IllegalStateException: No ViewModelStoreOwner was provided via LocalViewModelStoreOwner in CompatComposeView
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2912 +/- ##
=======================================
Coverage 78.45% 78.45%
=======================================
Files 332 332
Lines 12884 12884
Branches 1749 1749
=======================================
Hits 10108 10108
Misses 2042 2042
Partials 734 734 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
tonidero
left a comment
There was a problem hiding this comment.
I think it might be good documenting a bit more the reason of the crash, but if we've tested this changes seem reasonable
JayShortway
left a comment
There was a problem hiding this comment.
Awesome job fixing this! 💪
| } | ||
| if (windowRoot.findViewTreeSavedStateRegistryOwner() == null) { | ||
| windowRoot.setViewTreeSavedStateRegistryOwner(this) | ||
| isManagingViewTree = true |
There was a problem hiding this comment.
Maybe we should set an additional boolean here (isManagingSavedState), and use it in these places:
override fun onSaveInstanceState(): Parcelable? {
val state = super.onSaveInstanceState()
if (isManagingSavedState) performSave(state)
return state
}
override fun onRestoreInstanceState(state: Parcelable?) {
super.onRestoreInstanceState(state)
if (isManagingSavedState) performRestore(state)
}
override fun onAttachedToWindow() {
initViewTreeOwners()
if (isManagingSavedState) {
savedStateRegistryController.performAttach()
performRestore(null)
}
// ...
}Otherwise we might be "managing" the saved state even if the view tree has a SavedStateRegistryOwner already.
There was a problem hiding this comment.
right! I think that makes sense
| } | ||
| if (windowRoot.findViewTreeViewModelStoreOwner() == null) { | ||
| windowRoot.setViewTreeViewModelStoreOwner(this) | ||
| isManagingViewTree = true |
There was a problem hiding this comment.
Same here, maybe we should set an additional boolean (isManagingViewTreeViewModelStore), and use it here:
override fun onDetachedFromWindow() {
// ...
if (isManagingViewTreeViewModelStore) viewModelStore.clear()
// ...
}Although I don't think it can hurt much if we're clearing a ViewModelStore that isn't actually being used.
tonidero
left a comment
There was a problem hiding this comment.
Makes sense, thanks again for the fix!!
**This is an automatic release.** > [!WARNING] > If you don't have any login system in your app, please make sure your one-time purchase products have been correctly configured in the RevenueCat dashboard as either consumable or non-consumable. If they're incorrectly configured as consumables, RevenueCat will consume these purchases. This means that users won't be able to restore them from version 9.0.0 onward. > Non-consumables are products that are meant to be bought only once, for example, lifetime subscriptions. ## RevenueCat SDK ### 📦 Dependency Updates * [RENOVATE] Update build-dependencies to v8.13.2 (#2929) via RevenueCat Git Bot (@RCGitBot) ## RevenueCatUI SDK ### 🐞 Bugfixes * Fix `IllegalStateException`: No `ViewModelStoreOwner` was provided via `LocalViewModelStoreOwner` in `CompatComposeView` (#2912) via Cesar de la Vega (@vegaro) ### 🔄 Other Changes * Change AdFailedToLoad mediatorErrorCode type from Long to Int (#2924) via Pol Miro (@polmiro) * Change paywall preview recorder name template (#2923) via Toni Rico (@tonidero) * Don't use reflection to instantiate AmazonDeviceIdentifiersFetcher (#2919) via Will Taylor (@fire-at-will) Co-authored-by: revenuecat-ops <ops@revenuecat.com>
We got a report that in Expo 54 the app crashes with this exception when presenting a paywall in a Modal:
I was debugging and noticed that when it hits this line:
in Expo < 54,
findViewTreeLifecycleOwner,findViewTreeLifecycleOwner,findViewTreeSavedStateRegistryOwnerall null.in Expo 54,
windowRoot.findViewTreeLifecycleOwner()returns!= null, so it skips the rest