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 display a Toast! Yes, Snackbar is the new cool kid, but toasts tastes better.
πππππ.πππππππ‘π(ππππππ‘π, "

ππππππ‘π should be...

"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
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
One approach to avoid this is a custom context wrapper that catches BadTokenException
E.g. https://github.com/PureWriter/ToastCompat or https://github.com/LouisCAD/Splitties/blob/main/modules/toast/src/androidMain/kotlin/splitties/toast/Toast.kt#L88-L113 by @Louis_CAD (still could leak activity though)
E.g. https://github.com/PureWriter/ToastCompat or https://github.com/LouisCAD/Splitties/blob/main/modules/toast/src/androidMain/kotlin/splitties/toast/Toast.kt#L88-L113 by @Louis_CAD (still could leak activity though)
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!
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.