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 75 forks source link

Multiple stacks + shared scope between different stacks #247

Closed MFlisar closed 3 years ago

MFlisar commented 3 years ago

Is that somehow possible? I found your example about bottom navigation + one stack per bottom navigation item. What I have is following:

Now I want that fragments inside different bottom navigation items can communicate with each other - actually like you do it in this example.

The problem are the multiple stacks and I don't know how I can pass data between multiple stacks. Any ideas how this can be solved?

Zhuinden commented 3 years ago

Technically the only shared scope between the substacks hosted by the fragments are within the Activity-level backstack, so you'd most likely need to communicate through a shared parent in there, possibly using something like https://github.com/Zhuinden/event-emitter (or its lifecycle-wrapper variant) so that they process the event when they come into view.

Please note that an EventEmitter does not persist its values across process death, so if such pending values are needed, I'd set them as a field (probably within a BehaviorRelay when using Rx) and save/restore it with Bundleable.

So technically, go through the parent if you need to talk across stacks, those are completely independent. 🤔

MFlisar commented 3 years ago

Thanks for the feedback - I may use some of the default technics like a shared androidx ViewModel inside the main activity...

By the way, if stacks can be linked to parent stacks, my problem could be solved inside your library as well - if I understand your own open issue correctly. Actually I was hoping I can somehow do this already...

Zhuinden commented 3 years ago

Well technically "linking to a parent stack" is as simple as

if(localStack.canFind<T>()) { 
    return localStack.lookup<T>() 
} else { 
    return parentStack.lookup<T>()
}

I just couldn't figure out an API that would make it sense that lifecycle callbacks still need to be managed manually (which is why the child fragments are involved that call the methods on Backstack, right?). So it isn't impossible, you just have to do the check yourself.

Using canFind + lookup should be sufficient to solve the issue though.

Zhuinden commented 3 years ago

Did this help answer the question?

MFlisar commented 3 years ago

I'm not sure how you access the parentStack or how you meant this...

But as I do manage the fragments manually inside the root view with the bottom sheet I simply pass on the root backstack to the FragmentStackHostFragment and then each fragment inside the FragmentStackHostFragment is able to access the root backstack as well.

Zhuinden commented 3 years ago

parentStack should be the same as Fragment.backstack which is the same as Navigator.getBackstack(requireContext()) if the nesting level is 1

But yeah, if you do see both, then it really is a matter of checking with canFind and then delegating one up if not found. I still haven't found an API that would make perfect sense if I were to make it in order to make this happen within the framework, but as it's only a few lines i think it should be ok

MFlisar commented 3 years ago

But yeah, if you do see both, then it really is a matter of checking with canFind

Actually, I do know where the desired item is in, so I can directly use the correct backstack, But with your suggestion I don't even need to know this and I can use a "fullLookup" function like following inside the FragmentStackHostFragment:

inline fun <reified T : Any> fullLookup(serviceTag: String = T::class.java.name): T {
    if (stackHost.backstack.canFind<T>()) {
        // return the item from local backstack
        return stackHost.backstack.lookup(serviceTag)
    } else {
        // fall back to global backstack and try to find it there
        return backstack.lookup(serviceTag)
    }
}

Thanks for your feedback, it solved my problem

Zhuinden commented 3 years ago

Glad to hear it helped resolve your issue 🎉

Zhuinden commented 1 year ago

While I'm pretty sure this is effectively obsolete by now as it's been 2 years, but the feature was added directly to Simple-Stack as per https://github.com/Zhuinden/simple-stack/issues/239