Code puzzle for all #AndroidDev out there!

Let's display a Toast! Yes, Snackbar is the new cool kid, but toasts tastes better.

πšƒπš˜πšŠπšœπš.πš–πšŠπš”πšŽπšƒπšŽπš‘πš(πšŒπš˜πš—πšπšŽπš‘πš, "πŸ€”", π™»π™΄π™½π™Άπšƒπ™·_𝙻𝙾𝙽𝙢).πšœπš‘πš˜πš ()

πšŒπš˜πš—πšπšŽπš‘πš should be...
🧡 Let's look at each possible answer!

"an Activity Instance"

=> Toasts are enqueued and displayed serially. Each stays for 2-3.5 seconds. Until toast is displayed, the activity will be held in memory even after Activity#onDestroy().

Enqueue several toasts => activity leak!
"an Application instance"

This is the right answer to avoid Activity leaks. However, on API 25, there's a race condition leading to crashes when the app is in background: BadTokenException. Not just activity though, this happens with every context!

See https://android.googlesource.com/platform/frameworks/base/+/0df3702f533667a3825ecbce67db0853385a99ab%5E%21/core/java/android/widget/Toast.java
Another approach is to use an Activity context but cancel the toasts when that Activity is destroyed. After all, should you really display a toast after the activity has been destroyed? Users hate toasts randomly appearing!
I'm making LeakCanary better at surfacing this edge case: when a ViewRootImpl is held by WindowManagerGlobal and references a destroyed activity, LeakCanary will now hint that you might need to cancel a toast (the activity ViewRootImpl is automatically removed)
So, what's the right answer?

Obviously: don't use Toast, use Snackbar!
But if you really want to use Toast: either use an application context with a horrible context wrapper hack, OR use whatever context and cancel toasts on activity destroy.
You can follow @Piwai.
Tip: mention @twtextapp on a Twitter thread with the keyword β€œunroll” to get a link to it.

Latest Threads Unrolled:

By continuing to use the site, you are consenting to the use of cookies as explained in our Cookie Policy to improve your experience.