Firebase Android PhoneAuthProvider导致内存泄漏

时间:2019-07-02 13:28:31

标签: java android firebase-authentication

Firebase-> PhoneAuthProvider-> VerifyPhoneNumber正在泄漏。我相信可能是OnVerificationStateChangedCallbacks,我们正在通话时将其发送到verifyPhoneNumber。

复制步骤:

  1. 启动应用
  2. 选择“ PhoneAuthActivity”进行基于电话的身份验证
  3. 发送电话号码。
  4. 单击返回。

单击后,将显示泄漏的内存

有人有同样的问题吗?有什么办法吗?

public void FirebasePhoneUser(String phoneNumber) {
            mCallback = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
                @Override
                public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
                    Log.d("Completed","");
                }
                @Override
                public void onVerificationFailed(FirebaseException e) {
                    Log.d("Error","");
                }

                @Override
                public void onCodeSent(String verificationId,
                                  PhoneAuthProvider.ForceResendingToken forceResendingToken) {
                    Log.d("onCodeSent", "");
                }
            };
            phoneAuthProvider = PhoneAuthProvider.getInstance();
            phoneAuthProvider.verifyPhoneNumber(
                    phoneNumber,
                    30,
                    TimeUnit.SECONDS,
                    TaskExecutors.MAIN_THREAD,
                    mCallback
            );
}

1 个答案:

答案 0 :(得分:2)

鉴于API很糟糕,没有取消订阅的选项,您可以通过多种方法解决此问题。

  1. 代理或装饰器。您创建另一个OnVerificationStateChangedCallbacks,它将方法调用委托给另一个实例:
// this class must be either top-level or 'static'!
public /*static*/ final class DelegatingVerificationStateCallbacks
    extends PhoneAuthProvider.OnVerificationStateChangedCallbacks
    implements Closeable {
    @Nullable private PhoneAuthProvider.OnVerificationStateChangedCallbacks delegate;
    public DelegatingVerificationStateCallbacks(
        @NonNull PhoneAuthProvider.OnVerificationStateChangedCallbacks delegate
    ) {
        this.delegate = delegate;
    }

    @Override public void onCodeSent(
        @NonNull String verificationId,
        @NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken
    ) {
        if (delegate != null) delegate.onCodeSent(verificationId, forceResendingToken);
    }
    @Override public void onCodeAutoRetrievalTimeOut(@NonNull String s) {
        if (delegate != null) delegate.onCodeAutoRetrievalTimeOut(s);
    }
    @Override public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {
        if (delegate != null) delegate.onVerificationCompleted(phoneAuthCredential);
    }
    @Override public void onVerificationFailed(@NonNull FirebaseException e) {
        if (delegate != null) delegate.onVerificationFailed(e);
    }

    @Override public void close() {
        delegate = null;
    }
}

我已经实现了Closeable进行清理,但是您可以实现RxJava的Disposable或其他任何方法。

这里的使用模式是显而易见的并且众所周知:

public final class SomeScreen extends ActivityOrFragmentOrControllerOrWhatever {
    private final ArrayList<Closeable> disposeBag = new ArrayList<>();
    private void performAuth() {
        DelegatingVerificationStateCallbacks callbacks =
            new DelegatingVerificationStateCallbacks(
                new OnVerificationStateChangedCallbacks() { … }
            );
        disposeBag.add(callbacks);
        phoneAuthProvider.verifyPhoneNumber(…, callbacks);
    }
    @Override protected void onDestroy() {
        for (Closeable c : disposeBag) {
            try { c.close(); }
            catch (IOException ignored) { }
        }
        disposeBag.clear();
    }
}

结果:Firebase泄漏了对空的和便宜的DelegatingVerificationStateCallbacks的引用,而不是对Activity的引用。

  1. 消零引用自己。您可以采用上面介绍的方法来清除自己对“活动”的引用。这意味着这些引用必须是明确的,即。 e。该类不得匿名或在您的活动之内。您必须完全控制类的构造函数和字段,最适合使用顶级类或嵌套的static类。

  2. 参考不足。这虽然不太明确,但是涉及到一些间接的操作,但是仍然可以使用:实例化顶级或嵌套的static类,将Activity传递给构造函数,将其包装在WeakReference中,然后分配给一个字段。就是这样,一段时间后WeakReference#get将开始返回null

  3. 反射。非常糟糕且不稳定的选项,在其他情况下可能会有所帮助。有时,您的活动可能会被Android SDK或特定于供应商的代码泄漏,并且上述选项不适用。然后,您可以自己取消一些私有字段。请勿对Firebase执行此操作。