【问题标题】:Updating AtomicBoolean from within lambda expression从 lambda 表达式中更新 AtomicBoolean
【发布时间】:2020-08-06 11:29:25
【问题描述】:

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

我已经尝试了一些方法。目前,我有一个名为successAtomicBoolean。在 lambda 表达式中,我调用了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()));
}

【问题讨论】:

  • 请向我们展示代码 - 很难找出我们看不到的代码有什么问题。如果您可以将其减少到minimal reproducible example,那就更好了。
  • 是的,您的描述没有任何问题,需要代码示例。
  • 对不起,我已经更新了代码
  • @Brian16446 你确定回调在你退出方法之前运行了吗?
  • 我怀疑signUp 方法是异步的:它立即返回并在另一个线程上运行。因此,当您检查它时,您的布尔值不会被设置。

标签: java android asynchronous aws-lambda aws-amplify


【解决方案1】:

如果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(); //you may want to add a timeout here
Log.d("success", String.valueOf(success.get()));

【讨论】:

  • 我尝试在网上寻找注册方法,但在任何地方都找不到,而且 android amplify 文档也不是很好。我会试试这个谢谢
  • @Brian16446 signUp(..) 方法记录在本节“注册用户”中:docs.amplify.aws/lib/auth/signin/q/platform/…
  • @Jameson 是的,我看到了,我的意思是我找不到有关返回类型、所有可选参数等的信息
【解决方案2】:

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()));之后被调用。

【讨论】:

    【解决方案3】:

    @assylias 和@jakub-bialy 的回答完全有效。但是,两者都没有考虑 error 回调。此外,直接使用CountDownLatch 有点低级。

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

    在您的情况下,您可以使用the Rx version of the signUp(...) method,如下所示:

    // 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 被忽略了。

    【讨论】:

    • 这很好,这些链接很有帮助,谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多