从lambda表达式内部更新AtomicBoolean

huangapple go评论78阅读模式
英文:

Updating AtomicBoolean from within lambda expression

问题

I'm passing a lambda expression as an argument to a method, and I want to modify a variable that is defined outside of the lambda expression.

我正在将一个Lambda表达式作为参数传递给一个方法,并且我想修改在Lambda表达式之外定义的变量。

I've tried a few things. Currently, I have an AtomicBoolean called success. Within the lambda expression, I'm calling success.set(true). However, when I log the value of the success variable, it's still false and doesn't seem to be updating.

我尝试了一些方法。目前,我有一个名为successAtomicBoolean。在Lambda表达式内部,我调用了success.set(true)。然而,当我记录success变量的值时,它仍然是false,似乎没有更新。

Basically, I'm calling a function with a void return type and need to know if the function was successful.

基本上,我正在调用一个返回void类型的函数,需要知道函数是否成功。

What am I doing wrong?

我做错了什么?

Here's the code:

这是代码:

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()));
}
英文:

I'm passing a lambda expression as an argument to a method, and I want to modify a variable that is defined outside of the lambda expression.

I've tried a few things. Currently, I have an AtomicBoolean called success. Within the lambda expression, I'm calling success.set(true). However, when I log the value of the success variable, it's still false and doesn't seem to be updating.

Basically, I'm calling a function with a void return type and need to know if the function was successful.

What am I doing wrong?

Here's the code:

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()));
}

答案1

得分: 2

如果signUp方法是阻塞的(即在注册完成后返回),则您的代码应该按预期工作。因此,我怀疑它是异步的。

在这种情况下,除了使用布尔值之外,您还可以使用CountDownLatch来等待异步方法完成:

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(); //您可能想要在此处添加超时
Log.d("success", String.valueOf(success.get()));
英文:

If the signUp method is blocking (i.e. it returns once the signup is finished), your code should work as expected. So I suspect it is asynchronous.

In that case, on top of using a boolean, you could also use a CountDownLatch to wait until the async method completes:

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()));

答案2

得分: 1

An AtomicBoolean variable (success) is used correctly. Most probably,

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

is called before

result -> success.set(true)

because of asynchronous execution of callback. Alternatively result callback is not called at all.

You can test it by changing callback body to:

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

If "callback test" doesn't appear in the logs then callback is not called.
If "callback test" appears after "success" then callback body is called after Log.d("success", String.valueOf(success.get())); due to asynchronous execution.

英文:

An AtomicBoolean variable (success) is used correctly. Most probably,

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

is called before

result -> success.set(true)

because of asynchronous execution of callback. Alternatively result callback is not called at all.

You can test it by changing callback body to:

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

If &quot;callback test&quot; doesn't appear in the logs then callback is not called.<br>
If &quot;callback test&quot; appear after &quot;success&quot; then callback body is called after Log.d(&quot;success&quot;, String.valueOf(success.get())); due to asynchronous execution.

答案3

得分: 1

@assylias 和 @jakub-bialy 的答案是完全有效的。但是,它们都没有考虑到 error 回调函数。另外,直接使用 CountDownLatch 有点底层。

Amplify 提供了一个 rxbindings 模块,可以帮助简化异步编程。

在你的情况下,你可以使用 signUp(...) 方法的 Rx 版本,像这样:

// 将初始化更改为:
RxAmplify.addPlugin(new AWSCognitoAuthPlugin())
RxAmplify.configure(getApplicationContext())

// 阻塞方式进行注册:
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 被忽略了。

英文:

@assylias's and @jakub-bialy's answers are totally valid. However, neither considers the error callback. Additionally, using a CountDownLatch directly is a little low-level.

Amplify provides an rxbindings module, which can help simplify asynchronous programming.

In your case, you could use the Rx version of the signUp(...) method, like so:

// 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();

The signUp(...) call in this case will throw the error in a blocking way, in the thread that makes the call. In the other answers, this error is ignored.

huangapple
  • 本文由 发表于 2020年8月6日 19:29:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/63282617.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定