Create a Sequencing snackbar feature #10856
Conversation
…app. Leaving show method only where duration was Snackbar.LENGTH_INDEFINITE
Generated by 🚫 dangerJS |
|
You can test the changes on this Pull Request by downloading the APK here. |
malinajirka
left a comment
There was a problem hiding this comment.
Thanks @develric, great job;)!
The tests look really good. I have left just one minor comment.
We might want to consider adding a test which would test the capacity. I'm not sure it's worth it, only if it would be straightforward. Wdyt?
I'd also consider decreasing the capacity to 5 items -> I can't imagine a real case scenario in which we'd like to show 30+ seconds old snackbar. Wdyt?
I'm going to test the behavior now. ;)
WordPress/src/test/java/org/wordpress/android/util/SnackbarSequencerConcurrentTest.kt
Show resolved
Hide resolved
WordPress/src/main/java/org/wordpress/android/util/SnackbarSequencer.kt
Outdated
Show resolved
Hide resolved
|
I've tested the app and it works as expected except of the animation issue I mentioned above. It seems the PostsListActivity is getting gc collected even when there are pending snackbars, so that's working as expected as well ;). @planarvoid Since we wrote big parts of the code with Riccardo, I'll leave the review + approval + merge to you. Thanks! ;) |
WordPress/src/main/java/org/wordpress/android/util/SnackbarSequencerInfo.kt
Outdated
Show resolved
Hide resolved
| get() = bgDispatcher + job | ||
|
|
||
| fun enqueue(item: SnackbarSequencerInfo) { | ||
| synchronized(this@SnackbarSequencer) { |
There was a problem hiding this comment.
I'd consider using launch(mainThread) here instead since using the main thread would ensure synchronous access and I think it makes it easier to understand. There is also no heavy work on the thread so I don't think it's even necessary to go on the bg thread.
There was a problem hiding this comment.
Ohh, great idea! I was curious so I tested it and it works as expected and the code is easier to understand.
There was a problem hiding this comment.
Here is a patch in case you want to use it @develric - https://cloudup.com/cdAXfGQft6N
There was a problem hiding this comment.
Makes sense, thanks for the patch 👍!
WordPress/src/main/java/org/wordpress/android/util/SnackbarSequencerInfo.kt
Outdated
Show resolved
Hide resolved
|
Hi @malinajirka and @planarvoid , i should have followed up to all your comments. Waiting for your second pass review, thanks! 😊 |
malinajirka
left a comment
There was a problem hiding this comment.
Thanks @develric for all the changes ;)! (Great suggestions @planarvoid !)
I've reviewed the changes + tested the app + verified the activity is not leaking. LGTM - I'll leave the final review to Vojta!
WordPress/src/test/java/org/wordpress/android/util/SnackbarSequencerConcurrentTest.kt
Outdated
Show resolved
Hide resolved
WordPress/src/test/java/org/wordpress/android/util/SnackbarSequencerConcurrentTest.kt
Outdated
Show resolved
Hide resolved
| advanceTimeBy(checkPoints[0] - 2 * SNACKBAR_DURATION_MARGIN) | ||
| verify(wpSnackbar, times(1)).show() | ||
| advanceTimeBy(2 * SNACKBAR_DURATION_MARGIN) | ||
| verify(wpSnackbar, times(2)).show() |
There was a problem hiding this comment.
We might want to consider removing all the lines below this line (exclusive). I think we are technically testing the same thing as "snackbars are shown in sequence with the correct duration".It would make the purpose of the test clearer imo. Wdyt?
There was a problem hiding this comment.
Well, I think you are right 😊! Let me know what you think of my answers to the previous points and I will change also this one as you suggested, thanks 🙇♂️!
There was a problem hiding this comment.
Maybe we can consider this addressed here?
planarvoid
left a comment
There was a problem hiding this comment.
Looks good 👍, I have two minor comments and I need to spend a little more time testing this PR :-)
|
|
||
| const val INDEFINITE_SNACKBAR_NOT_ALLOWED = "Snackbar.LENGTH_INDEFINITE not allowed in getSnackbarDurationMs." | ||
|
|
||
| fun getSnackbarDurationMs(snackbarItem: SnackbarItem): Long { |
There was a problem hiding this comment.
Do you think this could be a method in the SnackbarItem class? I think it would make it little better 👍
planarvoid
left a comment
There was a problem hiding this comment.
I think it works well, good job! So much better than before 👍 I don't feel strongly about the tests so feel free to change them or leave them as they are.
WordPress/src/test/java/org/wordpress/android/util/SnackbarSequencerConcurrentTest.kt
Outdated
Show resolved
Hide resolved
|
Hey @malinajirka, @planarvoid ! Thanks both of you for the thorough review and comments! I hope I followed up to all of them accordingly. Let me know wdyt! 😊 |
malinajirka
left a comment
There was a problem hiding this comment.
LGTM, thank you for both for the suggestions + changes 🙇
|
While working on some other feature I need to user Snackbars for, found out about the Sequencer and so came here looking for info about why / how the Sequencer was needed, given the following:
collided with my assumptions about how Snackbars work, as can be read in the training documentation:
I ran a quick test and called Snackbar several times only to confirm what you guys noted - any snackbar currently being shown on the screen will be closed immediately as a new call to Been reading the code implementation of Snackbar and SnackbarManager in the support library. Looks like other people have discovered the same issue as well, but their workarounds are much simpler given they still could count on I guess this is yet another inconsistency in the Android OS 🙃 - I wonder why they don't fix it Thanks for the work done here @develric @malinajirka @planarvoid , hope this can help others as well. 👏 |
Fixes #10771 and supersedes #10820
The code in this PR was mostly done in Pair Programming/Brainstorming with @malinajirka , so credits to him 🙇♂️.
The basic idea is to introduce a snackbar sequencer to avoid that multiple snackbars, triggered nearly together, overlap not allowing to the user to check/understand the ongoing messages. We introduced a SnackbarSequencer class and a SnackbarSequencerInfo class. The client code can enqueue SnackbarSequencerInfo element into the SnackbarSequencer instead of directly use the WPSnackbar class. In this way the sequencer consumes the queue of SnackbarSequencerInfo visualuazing in sequence the snackbars.
To avoid memory leaks due to the fact that we keep into the sequencer queue references to view/context and listeners that can eventually be no more active at the time we try to show the snackbar, we keep those references as Weak/Soft references.
For now we have used the sequencer only in upload posts related snackbars to limit the impact as much as possible to the #10771 issue. It will be eventually extended in a future time to all snackbars. NOTE: only snackbars that are not
Snackbar.LENGTH_INDEFINITEare allowed, otherwise anIllegalArgumentExceptionis triggered.For the unit testing we introduced
kotlinx-coroutines-testversion 1.2.1 in the testImplementation tree. In this way we can use theadvanceTimeByfunction to test the coroutine/delay.Pinging also @planarvoid to have a third couple of eyes on it.
To test:
SnackbarSequencer.start(inval item = snackBarQueue.peek())SnackbarSequencer > start context was nullorSnackbarSequencer > start context was not alive(this means the snackbar got the Activity was no more valid)PR submission checklist:
I have considered adding unit tests where possible.
I have considered if this change warrants user-facing release notes and have added them to
RELEASE-NOTES.txtif necessary.