Repository: square/leakcanary
Issue: ToastEventListener leak

### Description
Hi all,

I receive two notifications from Leakcanary when debugging an app on a Samsung Galaxy S10 running on Android 12.

Indeed, Leakcanary notifies a leaked activity when the concerned activity is recreated (toggling from light to night mode or vice versa, and rotating screen, in my case).

Below are shown the Leakcanary reports:

FIRST REPORT
```┬───
│ GC Root: System class
│
├─ android.view.inputmethod.InputMethodManager class
│    Leaking: NO (InputMethodManager↓ is not leaking and a class is never
│    leaking)
│    ↓ static InputMethodManager.sInstance
├─ android.view.inputmethod.InputMethodManager instance
│    Leaking: NO (DecorView↓ is not leaking and InputMethodManager is a
│    singleton)
│    ↓ InputMethodManager.mCurRootView
├─ android.view.ViewRootImpl instance
│    Leaking: NO (DecorView↓ is not leaking)
│    mContext instance of com.android.internal.policy.DecorContext, wrapping
│    activity my_package.MainActivity with mDestroyed = false
│    ViewRootImpl#mView is not null
│    mWindowAttributes.mTitle = "my_package/my_package.
│    MainActivity"
│    mWindowAttributes.type = 1
│    ↓ ViewRootImpl.mParentDecorView
├─ com.android.internal.policy.DecorView instance
│    Leaking: NO (View attached)
│    View is part of a window view hierarchy
│    View.mAttachInfo is not null (view attached)
│    View.mWindowAttachCount = 1
│    mContext instance of com.android.internal.policy.DecorContext, wrapping
│    activity my_package.MainActivity with mDestroyed = false
│    ↓ DecorView.mMSActions
│                ~~~~~~~~~~
├─ com.samsung.android.multiwindow.MultiSplitActions instance
│    Leaking: UNKNOWN
│    Retaining 43 B in 1 objects
│    ↓ MultiSplitActions.mWindow
│                        ~~~~~~~
├─ com.android.internal.policy.PhoneWindow instance
│    Leaking: YES (Window#mDestroyed is true)
│    Retaining 15,0 kB in 285 objects
│    mContext instance of my_package.MainActivity with mDestroyed =
│    true
│    mOnWindowDismissedCallback instance of my_package.MainActivity
│    with mDestroyed = true
│    ↓ Window.mContext
╰→ my_package.MainActivity instance
​     Leaking: YES (ObjectWatcher was watching this because my_package.MainActivity received Activity#onDestroy() callback and
​     Activity#mDestroyed is true)
​     Retaining 6,4 kB in 226 objects
​     key = 7a5ee5de-103e-4f43-a3d1-2564ede0b638
​     watchDurationMillis = 11124
​     retainedDurationMillis = 6118
​     mApplication instance of android.app.Application
​     mBase instance of androidx.appcompat.view.ContextThemeWrapper

METADATA

Build.VERSION.SDK_INT: 31
Build.MANUFACTURER: samsung
LeakCanary version: 2.8.1
App process name: my_package
Stats: LruCache[maxSize=3000,hits=107193,misses=188802,hitRate=36%]
RandomAccess[bytes=9370928,reads=188802,travel=55908452413,range=31914653,size=3
9719368]
Analysis duration: 12542 ms
```

SECOND REPORT
```┬───
│ GC Root: Thread object
│
├─ android.os.HandlerThread instance
│    Leaking: NO (PathClassLoader↓ is not leaking)
│    Thread name: 'LeakCanary-Heap-Dump'
│    ↓ Thread.contextClassLoader
├─ dalvik.system.PathClassLoader instance
│    Leaking: NO (ToastEventListener↓ is not leaking and A ClassLoader is never
│    leaking)
│    ↓ ClassLoader.runtimeInternalObjects
├─ java.lang.Object[] array
│    Leaking: NO (ToastEventListener↓ is not leaking)
│    ↓ Object[1219]
├─ leakcanary.ToastEventListener class
│    Leaking: NO (a class is never leaking)
│    ↓ static ToastEventListener.toastCurrentlyShown
│                                ~~~~~~~~~~~~~~~~~~~
├─ android.widget.Toast instance
│    Leaking: UNKNOWN
│    Retaining 9,6 kB in 150 objects
│    mContext instance of my_package.MainActivity with mDestroyed =
│    false
│    ↓ Toast.mNextView
│            ~~~~~~~~~
╰→ android.widget.FrameLayout instance
​     Leaking: YES (ObjectWatcher was watching this because android.widget.
​     FrameLayout received View#onDetachedFromWindow() callback)
​     Retaining 9,5 kB in 148 objects
​     key = 21d82ba6-98f3-42a3-8496-d000912361c5
​     watchDurationMillis = 7325
​     retainedDurationMillis = 2322
​     View not part of a window view hierarchy
​     View.mAttachInfo is null (view detached)
​     View.mWindowAttachCount = 1
​     mContext instance of my_package.MainActivity with mDestroyed =
​     false

METADATA

Build.VERSION.SDK_INT: 31
Build.MANUFACTURER: samsung
LeakCanary version: 2.8.1
App process name: my_package
Stats: LruCache[maxSize=3000,hits=107890,misses=222607,hitRate=32%]
RandomAccess[bytes=12173060,reads=222607,travel=168156278612,range=60979699,size
=89197607]
Analysis duration: 11614 ms
```

### Version Information

* LeakCanary version: 2.8.1
* Android OS version: 12
* Gradle version: 7.3.3

### Additional Information

In my opinion, the first report is a bug related to Samsung and the second one is a Leakcanary bug.


Changed files:
leakcanary-android-core/src/main/java/leakcanary/ToastEventListener.kt

diff --git a/leakcanary-android-core/src/main/java/leakcanary/ToastEventListener.kt b/leakcanary-android-core/src/main/java/leakcanary/ToastEventListener.kt
index 6ad0b5dff..e05356c20 100644
--- a/leakcanary-android-core/src/main/java/leakcanary/ToastEventListener.kt
+++ b/leakcanary-android-core/src/main/java/leakcanary/ToastEventListener.kt
@@ -29,6 +29,7 @@ object ToastEventListener : EventListener {
       is HeapDump, is HeapDumpFailed -> {
         mainHandler.post {
           toastCurrentlyShown?.cancel()
+          toastCurrentlyShown = null
         }
       }
     }