Sure, here is the translation: Java Retrofit | 在lambda表达式中调用方法的返回值

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

Java Retrofit | Calling a method's return in a lambda expression

问题

public String userName(){
    // Retrofit setup here 
    MyAPI service = retrofit.create(MyAPI.class);
    Call<Users> call = service.getUser();
    
    final String[] userName = {null}; // Declare a final array to hold the user name
    
    call.enqueue(new Callback<Users>() {
        @Override
        public void onResponse(Call<Users> call, Response<Users> response) {
            // Suppose I get what I want here:
            userName[0] = response.body().getUserName();
        }

        @Override
        public void onFailure(Call<Users> call, Throwable throwable) {
            // Let's just say we return "User not found" onFailure
        }
    });
    
    // Wait for the callback to complete (not recommended for production)
    while (userName[0] == null) {
        // You can use Retrofit's isExecuted here if desired
    }
    
    return userName[0]; // Return the user name
}

Please note that the approach of using a while loop to wait for the callback to complete is not recommended for production code, as it can lead to performance and threading issues. It's better to design your code to work asynchronously with callbacks and avoid blocking the main thread.

英文:

Suppose I have this piece of code

public String userName(){
//Retrofit setup here 
MyAPI service = retrofit.create(MyAPI.class);
 Call&lt;Users&gt; call = service.getUser();
            call.enqueue(new Callback&lt;&gt;() {
                @Override
                public void onResponse(Call&lt;Users&gt; call, Response&lt;Users&gt; response) {
                  //suppose I get what I want here:
                  response.body().getUserName();
                }

                @Override
                public void onFailure(Call&lt;Users&gt; call, Throwable throwable) {
                   //let&#39;s just say we return &quot;User not found&quot; onFailure
                }
            });
//return statement here
}

Is there a way I can have the String return statement of the userName() method in lambda expression? If not, what's the simplest way (with minimal amounts of processing) I can use to achieve this.

Retrofit has a isExecuted method for calls so I was thinking about using that in a while loop. But I just wanted to know if there's an easier way to do it before I proceed.
Thank you.

答案1

得分: 0

不,这是不可能的。enqueue 的意思是:以异步方式执行这个操作。也就是说,不是现在,而是以后。

你在哪里写了 return statement here?那会在 onResponse/onFailure 方法之前执行,所以你不能把返回语句移到那里——你的方法必须在你想让返回语句在其之前运行的地方返回(因此,必须知道要返回什么),这使得那是不可能的。

这就是异步 API 的问题:与其编写代码,不如说是在与之对抗。这就是当你说'回调地狱'时人们所指的:你需要重新设计所有的代码,使得这个方法不需要返回任何值;相反,所有将依据返回值执行的代码都需要被封装在一个 lambda 中,并且传递给这个方法,这样你就可以调用那个 lambda(并将你想要返回的内容,比如 "User not found",作为参数传递)。

可能有办法在这里不使用 enqueue,我会首先看看那个方法。

英文:

No, that is not possible. enqueue means: Do this asynchronously. As in, not now, later.

Where you wrote return statement here? That runs before the onResponse/onFailure methods do, so you can't 'move' the return statement there - your method must return (and therefore, know what to return) before the place where you want the return statement to be has even run, which makes that impossible.

This is the problem with asynchronous API: They suck to code against. This is what people are talking about when you say 'callback hell': You need to redesign all your code so that this method needs to return nothing; instead, all code that would act upon the return value needs to be packed up in a lambda and shipped to this method, so that you can invoke that lambda (and pass the thing you want to return, such as &quot;User not found&quot;, as parameter instead).

There are probably ways to not use enqueue here, I'd look at that first.

huangapple
  • 本文由 发表于 2020年9月1日 21:44:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/63688973.html
匿名

发表评论

匿名网友

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

确定