-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Investigate setting ScopedServices with deferred initialization #243
Comments
Sorry, I did not have the chance to check this out until now. My use case is that I want scoped services to be provided by the dagger (sub)component. But this subcomponent needs backstack on its creation, which creates a bit of circular reference. Currently I'm solving this with the BackstackHolder pattern since none of the dependencies need Backstack immediately, but it is pretty hacky pattern. This is the furthest I've gotten without BackstackHolder, with deferred initialisation and backstack set after initialisation: val backstack = Navigator.configure()
.setStateChanger(AsyncStateChanger(composeStateChanger))
.setDeferredInitialization(true)
.install(this, androidContentFrame, History.of(GrocyListKey()))
val activityComponent = component.createActivitySubcomponentFactory().create(backstack)
backstack.setScopedServices(activityComponent.provideScopedServices())
Navigator.executeDeferredInitialization(this) However, this crashes with the following exception:
|
Oof, I see what you mean. Theoretically I could either say use assisted injection and rely on |
Not sure how assisted injection would help here. Then I would have to pass down Backstack manually throughout the whole injection chain which completely defeats the purpose of using DI (might as well continue using BackstackHolder) What if |
@matejdro released in 2.6.1. The restriction is now moved so that
I can't do that because of how state restoration works, but I don't think you'll need that for now. |
@matejdro While the issue is closed, please report back if this served your purposes 🚀 |
So basically your snippet with execute deferred init should work now #243 (comment) |
Wow that was fast. Thanks a lot! |
Actually, this does not seem to fix everything. After a configuration change, app still crashes on the
It seems to me that at this point, backstack is already set from the saved instance state (but scoped services are not, since they are bound to the activity, which is being recreated) and thus I cannot set scoped services. |
Technically, Backstack exists within the retained scope of the activity, so after rotation, you'd be getting the same Backstack instance which "had already had the state changer set". I do admit, I was testing this with unit tests, but not in an app. Theoretically, the following would still give you correct behavior: if(lastNonConfigurationInstance == null) {
backstack.setScopedServices(scopedServices)
} Assuming you aren't trying to pass in an Activity-reference or something. That would always be a memory leak, as the scopes are NOT recreated after config change. 🤔 The sample above is not ideal, but I am also not sure how I would reliably detect that it is allowed now. I guess similarly to when "force execute state change" is called ( Can you check if that works for you? |
Thanks, that worked. Yeah, I see now that setting scoped services at every start is a bit pointless, since they are retained. Maybe |
I will add a new method called |
Should be actually done now by 5d8b822 and 2.6.2, meaning that |
Confirmed working, thanks! |
@matejdro I see a new issue wasn't opened. Does
Navigator.configure().setDeferredInitialization(true)
+Navigator.executeDeferredInitialization
suit your needs? You effectively get a restored Backstack but without setting the StateChanger.The text was updated successfully, but these errors were encountered: