Open qwexter opened 1 month ago
Thank you for your report! We've added this to our internal board for review. ID: PM-10075
To solve the issue of duplicate navigation events, especially during rapid interactions or animations, you can implement a safety check using the current NavBackStackEntry
's lifecycle state. This approach is inspired by the Jetsnack sample from the Compose samples repository.
NavBackStackEntry
:/**
* If the lifecycle is not resumed it means this NavBackStackEntry already processed a nav event.
*
* This is used to de-duplicate navigation events.
*/
fun NavBackStackEntry.lifecycleIsResumed() =
this.lifecycle.currentState == Lifecycle.State.RESUMED
NavController
:fun NavController.safeNavigate(
route: String,
navOptions: NavOptions? = null,
navigatorExtras: Navigator.Extras? = null
) {
val navBackStackEntry = currentBackStackEntry
if (navBackStackEntry?.lifecycleIsResumed() == true) {
navigate(route, navOptions, navigatorExtras)
}
}
safeNavigate
instead of navigate
for all navigation actions.This solution ensures that navigation events are only processed when the current NavBackStackEntry
is in the RESUMED state, effectively preventing duplicate navigations during animations or rapid interactions.
For more context, you can refer to the implementation in the Jetsnack sample: https://github.com/android/compose-samples/blob/081721ad44dfb29b55b1bc34f83d693b6b8dc9dd/Jetsnack/app/src/main/java/com/example/jetsnack/ui/JetsnackAppState.kt#L146
For handling double-click issues in non-navigation events, you might want to consider this: https://android-review.googlesource.com/c/platform/frameworks/support/+/2944594
There's also 1st line of defense against this by simply debouncing taps by 300-500ms. It's just on UI level but we usually combine this with navigation guards proposed above since there might be some actions not related to nav.
Bitwarden Beta
Steps To Reproduce
Open the Bitwarden Android app. Rapidly tap any navigation button multiple times. Observe that multiple instances of the same screen are opened. Navigate back through the screens. Note the occurrence of empty screens or broken navigation requiring an app restart. Perform an action that involves a network request (e.g., synchronization). Rapidly initiate the action multiple times. Observe that multiple network requests are sent.
Expected Result
The app should process single events only once, preventing multiple instances of the same screen or multiple network requests from being triggered.
Actual Result
Multiple instances of the same screen can be opened, and multiple network requests can be sent, leading to broken navigation and potential app instability.
Screenshots or Videos
Additional Context
The Bitwarden Android app allows users to perform the same action multiple times when rapidly tapping buttons. This is particularly noticeable with navigation buttons, where multiple instances of the same screen can be opened. Navigating back through these screens can lead to empty screens or broken navigation, sometimes requiring a restart of the app. This issue also occurs with actions involving network requests, such as synchronization, resulting in multiple requests being sent.
This problem stems from how the app handles user events within the MVI and Compose architecture. It affects the entire app and should ideally be addressed at the architectural level.
Build Version
Version 2024.6.0
Environment Details
Issue Tracking Info