是什么导致我的 AlertDialog 在 Firebase 回调方法中泄漏?

What is causing my AlertDialog to leak in Firebase callback method?

我有一个使用 AlertDialog Builder 创建的 AlertDialog:

private void setProgressDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.alertDialogTheme);
        builder.setView(R.layout.alert_dialog_login_progress);
        mAlertDialog = builder.create();
        mAlertDialog.setCancelable(false);
        mAlertDialog.setCanceledOnTouchOutside(false);
        mAlertDialog.show();

    }

我正在使用 FirebaseAuth 的登录方法:

private void signIn() {

mAuth.signInWithEmailAndPassword(mEmail, mPassword)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (!task.isSuccessful()) {
                            mAlertDialog.dismiss();
                            Toast.makeText(LoginActivity.this, "Authentication failed.",
                                    Toast.LENGTH_SHORT).show();

                        }
                    }
                });

}

我已经将代码减少到这个程度,但它仍然会泄漏。我不会改变活动。 泄漏是因为我输入了错误的密码,并调用了.isSuccessful()方法。

我也在 UI 线程上尝试了 运行,但它仍然泄漏:

 runOnUiThread(new Runnable() {
   public void run() {
       mAlertDialog.dismiss();
       Toast.makeText(LoginActivity.this, "Authentication failed.",
       Toast.LENGTH_SHORT).show();                    
   }
 });

完整代码如下:

https://pastebin.com/bp4Xa6jx

这是漏洞:

┬───
│ GC Root: Local variable in native code
│
├─ android.os.HandlerThread instance
│    Leaking: NO (PathClassLoader↓ is not leaking)
│    Thread name: 'GoogleApiHandler'
│    ↓ Thread.contextClassLoader
├─ dalvik.system.PathClassLoader instance
│    Leaking: NO (InternalLeakCanary↓ is not leaking and A ClassLoader is never
│    leaking)
│    ↓ ClassLoader.runtimeInternalObjects
├─ java.lang.Object[] array
│    Leaking: NO (InternalLeakCanary↓ is not leaking)
│    ↓ Object[].[218]
├─ leakcanary.internal.InternalLeakCanary class
│    Leaking: NO (LoginActivity↓ is not leaking and a class is never leaking)
│    ↓ static InternalLeakCanary.resumedActivity
├─  instance
│    Leaking: NO (Activity#mDestroyed is false)
│    mApplication instance of android.app.Application
│    mBase instance of android.app.ContextImpl
│    ↓ LoginActivity.mAlertDialog
│                    ~~~~~~~~~~~~
├─ androidx.appcompat.app.AlertDialog instance
│    Leaking: UNKNOWN
│    Retaining 157.5 kB in 2114 objects
│    mContext instance of android.view.ContextThemeWrapper, wrapping activity
│     with mDestroyed = false
│    Dialog#mDecor is null
│    ↓ Dialog.mWindow
│             ~~~~~~~
├─ com.android.internal.policy.PhoneWindow instance
│    Leaking: UNKNOWN
│    Retaining 15.3 kB in 300 objects
│    mContext instance of android.view.ContextThemeWrapper, wrapping activity
│     with mDestroyed = false
│    Window#mDestroyed is false
│    ↓ PhoneWindow.mDecor
│                  ~~~~~~
╰→ com.android.internal.policy.DecorView instance
​     Leaking: YES (ObjectWatcher was watching this because com.android.
​     internal.policy.DecorView received View#onDetachedFromWindow() callback)
​     Retaining 4.7 kB in 42 objects
​     key = f381c0b5-587b-4d68-b453-be1c851ce257
​     watchDurationMillis = 31367
​     retainedDurationMillis = 26366
​     View not part of a window view hierarchy
​     View.mAttachInfo is null (view detached)
​     View.mWindowAttachCount = 1
​     mContext instance of android.view.ContextThemeWrapper, wrapping activity
​      with mDestroyed = false

为什么会漏水,我该如何解决?

在尝试找出问题几个小时后,当我在调用 mAlertDialog.dismiss();

后将 mAlertDialog 设置为 null 时,内存泄漏不再发生
mAlertDialog.dismiss();
mAlertDialog = null;
Toast.makeText(LoginActivity.this, "Authentication failed.",Toast.LENGTH_SHORT).show();

我不知道为什么会这样...但它阻止了泄漏的发生。