Open K1rakishou opened 3 years ago
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
}
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.ViewGroup.getChildCount()' on a null object reference
at com.bluelinelabs.conductor.Router.removeAllExceptVisibleAndUnowned(Router.java:901)
at com.bluelinelabs.conductor.Router.setBackstack(Router.java:409)
2020-12-10 16:44:24.715 E/KurobaEx: at com.bluelinelabs.conductor.ControllerHostedRouter.setBackstack(ControllerHostedRouter.java:113)
at com.github.k1rakishou.kurobanewnavstacktest.activity.MainActivity.attachRouterHacky(MainActivity.kt:119)
at com.github.k1rakishou.kurobanewnavstacktest.activity.MainActivity.onCreate(MainActivity.kt:41)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
... 13 more
I wonder whether there is a way to make this work.
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.
If you have a suggestion for an API improvement I would be open to considering it
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.