Zhuinden / simple-stack

[ACTIVE] Simple Stack, a backstack library / navigation framework for simpler navigation and state management (for fragments, views, or whatevers).
Apache License 2.0
1.36k stars 76 forks source link

Make GlobalServices.Factory receive the Backstack as a parameter in create() #231

Closed Zhuinden closed 4 years ago

Zhuinden commented 4 years ago

Reported on Slack, Navigator has a design oversight that requires passing in a class that has a lateinit var backstack: Backstack field into the GlobalServices.Factory in order to pass the Backstack to the factory, and therefore to lazy-initialized GlobalServices.

Unfortunately, GlobalServices.Factory's create() method has no args, and so changing this contract is a breaking change. I wasn't really planning on a 3.0.0 release at this time, so for now, I'll just post what you can do to resolve this conundrum.

Option 1:

Ditch Navigator, and instantiate Backstack manually. Keep it across config changes, and invoke the right methods (refer to tutorial step 1).

In this case however, passing backstack as a parameter to things is the responsibility of the library user. It is theoretically meant to be an ActivityRetainedScope'd object, which Hilt does support out of the box, but lifecycle integration is still required.

Option 2: (recommended):

class CustomGlobalServicesFactory: GlobalServices.Factory {
    lateinit var backstack: Backstack

    override fun create(): GlobalServices = 
        GlobalServices.builder()
            .add(SomeService(backstack)) // backstack is definitely set when this is called!
            // don't add the `backstack` as a global service
            .build()
}

And now you can do:

val globalServicesFactory = CustomGlobalServicesFactory()

val backstack = Navigator.configure()
           .setDeferredInitialization(true)
           .setGlobalServices(globalServicesFactory)
           .setStateChanger(SimpleStateChanger(this))
           .install(this, container, History.of(FirstScreen())`

globalServicesFactory.backstack = backstack

Navigator.executeDeferredInitialization(this)