TransWikia.com

Как сделать рефакторинг методов с одинаковыми коллбеками?

Stack Overflow на русском Asked by white-imp on December 9, 2020

Делаю аутентификацию на андроид по номеру телефона и есть два похожих метода.
Единственное отличие у них – это последний параметр: внутри обоих методов вызывается PhoneAuthProvider.getInstance().verifyPhoneNumber() и для одного случая он на вход принимает 5 параметров, для другого 6 (параметр mResendToken и есть эта разница).

Оба моих метода содержат идентичные коллбеки PhoneAuthProvider.OnVerificationStateChangedCallbacks()
которые я хочу отрефакторить, чтобы не было копипейста, но не знаю как, потому что внутри этих коллбеков я использую свои коллбеки callback.onReady() для возврата результатов.

Буду благодарен за любые варианты.

мой интерфейс Callback:

interface AuthCallback {
    void onReady(int phoneAuthState, String msg);
}

Один из этидх двух методов, которые нужно отрефакторить:

public void resendVerificationCode(String phoneNumber, UserPhoneRepositoryInterface.AuthCallback callback) {
    PhoneAuthProvider.getInstance().verifyPhoneNumber(
        phoneNumber,         // Phone number to verify
        60,               // Timeout duration
        TimeUnit.SECONDS,    // Unit of timeout
        TaskExecutors.MAIN_THREAD, // Executor
        new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

            @Override
            public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {
                Log.d(TAG, "onVerificationCompleted:" + phoneAuthCredential);
                mVerificationInProgress = false;

                callback.onReady(PhoneAuthState.STATE_VERIFY_SUCCESS, null);
            }

            @Override
            public void onVerificationFailed(@NonNull FirebaseException e) {
                Log.w(TAG, "onVerificationFailed", e);

                mVerificationInProgress = false;

                if (e instanceof FirebaseAuthInvalidCredentialsException) {
                    callback.onReady(PhoneAuthState.STATE_VERIFY_FAILED, "Invalid phone number.");
                } else if (e instanceof FirebaseTooManyRequestsException) {
                    callback.onReady(PhoneAuthState.STATE_VERIFY_FAILED, "The SMS quota has been exceeded.");
                }
            }

            @Override
            public void onCodeSent(@NonNull String verificationId,
                                   @NonNull PhoneAuthProvider.ForceResendingToken token) {
                Log.d(TAG, "onCodeSent:" + verificationId);

                mVerificationId = verificationId;
                mResendToken = token;

                callback.onReady(PhoneAuthState.STATE_CODE_SENT, "Code sent");
            }
        },          // OnVerificationStateChangedCallbacks
        mResendToken);       // ForceResendingToken from callbacks
}

2 Answers

Превратите анонимный внутренний класс в неанонимный нестатичный внутренний класс (т.е. чтобы он был определен в теле того же класса, что и метод resendVerificationCode) так, чтоб он принимал AuthCallback в конструктор:

class MyClass {

  private class PhoneAuthVerificationStateChangedHandler extends 
        PhoneAuthProvider.OnVerificationStateChangedCallbacks {

    private AuthCallback callback;

    public PhoneAuthVerificationStateChangedHandler(AuthCallback callback) {
        this.callback = callback;
    }

    @Override
    public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {
        Log.d(TAG, "onVerificationCompleted:" + phoneAuthCredential);
        mVerificationInProgress = false;

        callback.onReady(PhoneAuthState.STATE_VERIFY_SUCCESS, null);
    }

    @Override
    public void onVerificationFailed(@NonNull FirebaseException e) {
        // тот же код что и в анонимном классе
    }

    @Override
    public void onCodeSent(@NonNull String verificationId,
                           @NonNull PhoneAuthProvider.ForceResendingToken token) {
        // тот же код что и в анонимном классе
    }
 }

 // тут можно использовать созданный класс
 public void resendVerificationCode(String phoneNumber, UserPhoneRepositoryInterface.AuthCallback callback) {
    PhoneAuthProvider.getInstance().verifyPhoneNumber(
        phoneNumber,         // Phone number to verify
        60,               // Timeout duration
        TimeUnit.SECONDS,    // Unit of timeout
        TaskExecutors.MAIN_THREAD, // Executor
        new PhoneAuthVerificationStateChangedHandler(callback),
        mResendToken
    );
  } 

}

Это будет работать так как в экземпляре внутреннего классе, коим является PhoneAuthVerificationStateChangedHandler, есть неявная ссылка на объект внешнего класса MyClass и соответственно доступ к его полям типа mVerificationInProgress.

Correct answer by Roman Konoval on December 9, 2020

Варианты на вскидку:

  1. вынесите основной интерфейс в переменную, и передавате его внутрь двух разных методов с 5 и 6 параметрами соответственно.
  2. Возможно, если 6 параметром передать Null, то это будет равно вызову 5-параметр-функции. Тогда Этот параметр можно просто передавать на вход вашей фукции.

Answered by Георгий Чеботарев on December 9, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP