-
Notifications
You must be signed in to change notification settings - Fork 343
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
[Question] Replacing one controller with another upon configuration change #636
Comments
A little update. I figured out that maybe I should use Router.setBackstack() method to replace previous backstack with a new one without the controller that I want to remove but now I'm getting NPEs because the "container" view is null since I'm trying to do this before calling rebindIfNeeded(). override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
rootContainer = findViewById(R.id.root_container)
router = attachRouterHacky(this, rootContainer, savedInstanceState)
if (!router.hasRootController()) {
val controller = MainController()
controller.setControllerPresenterDelegate(this)
router.setRoot(RouterTransaction.with(controller))
}
}
private fun attachRouterHacky(
activity: Activity,
container: ViewGroup,
savedInstanceState: Bundle?
): Router {
BackgroundUtils.ensureMainThread()
val isSplitMode = isSplitMode(activity)
val router = LifecycleHandler.install(activity)
.getRouter(container, savedInstanceState)
if (savedInstanceState != null) {
val controllerTag = if (isSplitMode) {
SlideUiElementsController.CONTROLLER_TAG
} else {
SplitNavController.CONTROLLER_TAG
}
val result = router.findRouterWithControllerByTag(controllerTag)
if (result != null) {
val (foundRouter, foundController) = result
val backstackCopy = foundRouter.backstack
val index = backstackCopy.indexOfFirst { routerTransaction ->
(routerTransaction.controller as? BaseController)?.getControllerTag() == controllerTag
}
if (index >= 0) {
backstackCopy.removeAt(index)
foundRouter.setBackstack(backstackCopy, null)
}
}
}
router.rebindIfNeeded()
return router
}
I wonder whether there is a way to make this work. |
…change from Slide to Split layout which lead to nothing (couple of other bugs were fixed though). The problem is in inability (at least I don't know how) to remove controllers from backstack upon config change before calling router.rebindIfNeeded() (it results in NPEs, maybe it's a bug). Waiting for the devs' response bluelinelabs/Conductor#636
I suppose there is no ideal way to do what you're looking for. Your original attempt is the best bet given the currently available APIs. If you have a suggestion for an API improvement I would be open to considering it, but I'm not sure of a good way to facilitate something like this. |
I actually managed to find a hacky solution: originally I was trying to replace a child controller in the backstack (SlideUiElementsController and SplitNavController are children of MainController) and it didn't work because at that stage those child controllers do not have the container view (and it crashes), however this works when replacing MainController which is the root in my case. The state of all controllers is lost but that is expected and not a problems in my case since I store everything in ViewModels.
I guess the current API is fine, but having an ability to remove/replace child controller somewhere deep in the backstack before router.rebindIfNeeded() is called would be nice, right now it simply crashes. |
I have a controller in which I want to insert another controller, conditionally. If the phone is in portrait layout I want to add Portrait controller, if in landscape or if an additional setting is turned on then Landscape controller. I'm doing it the following way:
I'm using the same view (contentContainer) for both controllers and also using RetainViewMode.RETAIN_DETACH for all controllers.
The issue I'm having with this approach is that upon config change the old HomeController is still in the stack, it's getting rebound and then is destroyed (after
getChildRouter(contentContainer).setRoot(transaction)
) which is expected. I'm getting the following log:While everything seems to be working I wonder if there is an official way to handle this situation (without old controller getting recteated)? Maybe I can somehow remove this controller during the call
Conductor.attachRouter(this, rootContainer, savedInstanceState)
before setting the root controller onto the main router?I saw the MasterDetailController demo and that it uses two containers when the phone is in landscape orientation and two child routers but I wonder whether it's possible to only have one container.
The text was updated successfully, but these errors were encountered: