Firebase-> PhoneAuthProvider-> VerifyPhoneNumber正在泄漏。我相信可能是OnVerificationStateChangedCallbacks,我们正在通话时将其发送到verifyPhoneNumber。
复制步骤:
单击后,将显示泄漏的内存
有人有同样的问题吗?有什么办法吗?
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
);
}
答案 0 :(得分:2)
鉴于API很糟糕,没有取消订阅的选项,您可以通过多种方法解决此问题。
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的引用。
消零引用自己。您可以采用上面介绍的方法来清除自己对“活动”的引用。这意味着这些引用必须是明确的,即。 e。该类不得匿名或在您的活动之内。您必须完全控制类的构造函数和字段,最适合使用顶级类或嵌套的static
类。
参考不足。这虽然不太明确,但是涉及到一些间接的操作,但是仍然可以使用:实例化顶级或嵌套的static
类,将Activity传递给构造函数,将其包装在WeakReference中,然后分配给一个字段。就是这样,一段时间后WeakReference#get
将开始返回null
。
反射。非常糟糕且不稳定的选项,在其他情况下可能会有所帮助。有时,您的活动可能会被Android SDK或特定于供应商的代码泄漏,并且上述选项不适用。然后,您可以自己取消一些私有字段。请勿对Firebase执行此操作。