Обновление AtomicBoolean из лямбда-выражения - PullRequest
2 голосов
/ 06 августа 2020

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

Я пробовал несколько вещей. В настоящее время у меня есть AtomicBoolean под названием success. В лямбда-выражении я вызываю success.set(true). Однако, когда я регистрирую значение переменной success, оно все еще false и, похоже, не обновляется.

В основном я вызываю функцию с возвращаемым типом void и мне нужно узнать, была ли функция успешной.

Что я делаю не так?

Вот код:

public void createUser(String email, String password) {
    AtomicBoolean success = new AtomicBoolean(false);
    Amplify.Auth.signUp(
        email,
        password,
        AuthSignUpOptions.builder()
            .userAttribute(AuthUserAttributeKey.email(), email)
            .build(),
        result -> success.set(true),
        error -> Log.e("AuthQuickStart", "Sign up failed", error)
    );
    Log.d("success", String.valueOf(success.get()));
}

Ответы [ 3 ]

2 голосов
/ 06 августа 2020

Если метод signUp является блокирующим (т.е. он возвращается после завершения регистрации), ваш код должен работать должным образом. Поэтому я подозреваю, что это асинхронно.

В этом случае, помимо использования логического, вы также можете использовать CountDownLatch, чтобы дождаться завершения метода asyn c:

AtomicBoolean success = new AtomicBoolean(false);
CountDownLatch done = new CountDownLatch(1);
Amplify.Auth.signUp(
        email,
        password,
        AuthSignUpOptions.builder().userAttribute(AuthUserAttributeKey.email(), email).build(),
        result -> { success.set(true); done.countDown(); },
        error -> { Log.e("AuthQuickStart", "Sign up failed", error); done.countDown(); }
);
done.await(); //you may want to add a timeout here
Log.d("success", String.valueOf(success.get()));
1 голос
/ 06 августа 2020

Ответы @ assylias и @ jakub-bialy полностью действительны. Однако ни один из них не учитывает обратный вызов error. Кроме того, использование CountDownLatch напрямую является немного низкоуровневым.

Amplify предоставляет модуль rxbindings, который может помочь упростить асинхронное программирование.

В вашем В этом случае вы можете использовать версию Rx метода signUp(...) , например:

// Change your initialization to:
RxAmplify.addPlugin(new AWSCognitoAuthPlugin())
RxAmplify.configure(getApplicationContext())

// Sign-up, in a blocking way:
AuthSignUpOptions options = AuthSignUpOptions.builder()
    .userAttribute(AuthUserAttributeKey.email(), email)
    .build();
AuthSignUpResult result =
    RxAmplify.Auth.signUp(email, password, options)
        .timeout(10, TimeUnit.SECONDS)
        .blockingGet();

Вызов signUp(...) в этом случае вызовет error в блокировке Кстати, в потоке, который делает вызов. В других ответах это error игнорируется.

1 голос
/ 06 августа 2020

Переменная AtomicBoolean (success) используется правильно. Скорее всего,

Log.d("success", String.valueOf(success.get()));

вызывается перед

result -> success.set(true)

из-за асинхронного выполнения обратного вызова. В качестве альтернативы обратный вызов результата не вызывается вообще.

Вы можете проверить это, изменив тело обратного вызова на:

 result -> {
     Log.d("callback test", "callback start");
     result -> success.set(true);
     Log.d("callback test", "callback end");
}

Если "callback test" не отображается в журналы, то обратный вызов не вызывается.
Если "callback test" появляется после "success", то тело обратного вызова вызывается после Log.d("success", String.valueOf(success.get())); из-за асинхронного выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...