Тип возврата кинжала с асинхронным вызовом - PullRequest
0 голосов
/ 07 декабря 2018

Я пытаюсь вернуть указанный тип при использовании сторонней функции, которая использует обратный вызов.У меня есть интерфейс

public interface AuthenticationService {
    AuthResult signInEmailPassword(String username, String password, AuthListener listener);
}

При реализации интерфейса я вызываю асинхронную функцию AWS Cognito, которая использует обратный вызов.

public class AwsCognitoAuthenticator implements AuthenticationService {
    @Override
    public AuthResult signUp(String givenName, String username, String password, final AuthListener listener) {
        userPool.signUpInBackground(username, password, userAttributes, null, signupCallback);
    --> return result from signupCallback;
    }
}

Как я могу по-прежнему возвращать тип AuthResult при вызове этого метода (signUpInBackground)?(Я не хочу менять его на void, чтобы я мог использовать кинжал на интерфейсе).

Редактировать

Я пробовал много разных способов в кинжале, нобыли неудачны с моими попытками.Я пытаюсь внедрить приведенный ниже интерфейс в действие в виде поля.

@Component(modules = LoginModule.class)
public interface AuthenticationService {
    void signUp(String givenName, String username, String password, AuthListener listener);
    void signInEmailPassword(String username, String password, AuthListener listener);
    void changePassword(String oldPassword, String newPassword);
    void resetPassword();
    void signOut();
}

Модуль

@Module
public class LoginModule {
    @Provides
    AuthenticationService provideAuthService() {
        return new AwsCognitoAuthenticator();
    }
}

Затем я получаю ошибки для трех объявлений, которые имеют параметры в интерфейсе, говорящие

ошибка: этот метод не является допустимым методом предоставления, методом внедрения членов или методом фабрики подкомпонентов.Кинжал не может реализовать этот метод

1 Ответ

0 голосов
/ 08 декабря 2018

Не следует аннотировать интерфейсы, которые вы реализуете с помощью @Component.@Component означает, в частности, интерфейс, который определяет ваш граф связывания, который вы хотите, чтобы Dagger реализовал для вас.

@Component(modules = LoginModule.class)
public interface AuthenticationComponent {
  AuthenticationService getAuthenticationService();
}

Приведенный выше код говорит Dagger использовать перечисленные вами классы @Module и @Inject -аннотированные конструкторы, которые он находит для создания классов, перечисленных в компоненте.Здесь этим классом является AuthenticationService, и в соответствии с вашим LoginModule вы получите конкретный AwsCognitoAuthenticator.Dagger генерирует эту реализацию рядом с AuthenticationComponent, так что вы можете вызвать create, чтобы получить фабрику для полностью созданного AuthenticationService:

AuthenticationComponent authComponent = DaggerAuthenticationComponent.create();

Поскольку у вас есть одна привязка, и все, что она делает, это вызывает один конструкторВручную, вы не получите большой выгоды от Dagger здесь.Однако, если ваш график растет со временем, или если вы измените AwsCognitoAuthenticator, чтобы требовать других зависимостей, это может легко утянуть вес.


Теперь, когда Dagger не участвует в вашей структуре интерфейса AuthenticationService, вы можете сосредоточитьсяна создание чистого API.Прежде всего вам необходимо решить, будет ли AuthenticationService работать синхронно или асинхронно.Если вы возвращаете AuthResult, вам нужно будет его создать, поэтому вам, кажется, нужно синхронное поведение.Тем не менее, поскольку вы принимаете AuthListener, вы, похоже, готовы к асинхронному поведению.Как потребитель вашего API, я бы этого не понял.Вместо этого попробуйте выполнить одно из следующих действий:

  • Примите AuthListener для каждого из ваших методов и используйте его для обратного вызова.Тогда вы можете вернуть void.Предположительно, принимаемый вами AuthListener имеет метод, который может принимать AuthResult всякий раз, когда выполняется фоновая задача, и вы знаете результат.Большинство ваших методов будут возвращать void, потому что обычно нет AuthResult для синхронного возврата.

  • Возвращает ListenableFuture<AuthResult> вместо AuthResult.Это означает, что возвращаемое значение API является объектом, который может принимать прослушиватели, которые будут вызваны, когда AuthResult готов, поэтому вам больше не нужно принимать AuthListener в качестве параметра.Это немного дороже, потому что ListenableFuture нуждается в структурах данных, чтобы принять произвольное количество слушателей, но он может скомпоновать лучше (если, скажем, вам нужно слушать несколько экземпляров ListenableFuture одновременно).

  • Удвойте синхронный API, чтобы ваши методы AuthenticationService не возвращались до тех пор, пока не будет выполнена фоновая задача.В большинстве случаев это плохая идея, но это возможно, и тогда вы можете быть уверены, что у вас есть AuthResult немедленно, когда вам нужно вернуться.

...