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

What is the proper way to add a key to the top even if it already exists in the backstack? #267

Closed Stonos closed 1 year ago

Stonos commented 1 year ago

Hey,

I have a data class that extends DefaultFragmentKey and returns toString() in getFragmentTag(). I want to be able to add this key to the top of the backstack without navigating to any previous instance of it.

Things I've tried:

  1. backstack.goTo(newKey) This obviously doesn't work because it finds the key in the backstack and goes back to it.

  2. I've tried to manually add the key to the top of the history:

    fun Backstack.addToTop(newKey: Any) {
    val oldHistory = this.getHistory<Any>()
    val newHistory = oldHistory.buildUpon().add(newKey).build<Any>()
    setHistory(newHistory, StateChange.FORWARD)
    }

    This appears to work at first, but in reality the instance of the first Fragment is retained (I have a RecyclerView in the Fragment, and when I navigated again to the same key, the scroll position was the same as I left it in the previous instance of the same Fragment). I guess this happens because the keys/fragments have the same tag.

  3. I added val uuid: UUID = UUID.randomUUID() to my data class, as suggested here: https://github.com/Zhuinden/simple-stack/issues/261#issuecomment-1190648222 This works! However, this feels like a hacky solution, and I have to remember to add it to any key that could become part of a loop (i.e. appears in the backstack with the same parameters). Also, I'm not sure of the performance implications of using randomUUID() (probably insignificant, but it uses SecureRandom in its implementation).

Is there a better way to achieve this? Thanks!

Zhuinden commented 1 year ago

Hey hey!

I added val uuid: UUID = UUID.randomUUID() to my data class, as suggested here: https://github.com/Zhuinden/simple-stack/issues/261#issuecomment-1190648222 This works! However, this feels like a hacky solution, and I have to remember to add it to any key that could become part of a loop (i.e. appears in the backstack with the same parameters). Also, I'm not sure of the performance implications of using randomUUID() (probably insignificant, but it uses SecureRandom in its implementation).

Is there a better way to achieve this?

Well, you do need a stable string fragment tag (which is what data class + toString() does), I also do a val uuid: String = UUID.randomUUID().toString() when this is needed.

I'm not so sure it's that hacky, what the Google Navigation people do is that they have a static AtomicInteger being incremented so that each destination is indexed, but that wouldn't work well with asymmetric navigation actions (setHistory, bringToFront etc.) and I think it's way hackier than a uuid.

So if there's a better way, I don't know of it, but I do think this one makes sense. 😅

Stonos commented 1 year ago

I see, thanks for the response!