简体   繁体   English

如何等待改造异步Web服务调用? (call.enqueue)

[英]How do I await Retrofit async web service call? (call.enqueue)

I am new to java/android and have previously done a lot in C# with the use of async calls where I can use await to force a response before I move onto more code. 我是java / android的新手,以前在C#中使用异步调用做了很多工作,在我使用更多代码之前,可以使用await强制响应。

From what I can tell call.enqueue is asynchronous, but I want that to be awaited so that my LoginActivity method can handle the next steps based on if the login was successful or not. 据我所知,call.enqueue是异步的,但是我希望等待它,以便我的LoginActivity方法可以根据登录是否成功来处理下一步。

I made some Logs that ideally should be displayed as follows: 我制作了一些日志,理想情况下应显示如下:

FIRST
SECOND
THIRD
FOURTH

However because of the async, I instead get: 但是由于异步,我改为:

FIRST
SECOND
FOURTH
THIRD

LoginActivity.java LoginActivity.java

public boolean tryLoginAttempt(LoginRequest request) {
    // Call login service, login method
    LoginService service = new LoginService();

    Log.d(TAG, "FIRST");

    LoginResponse loginResponse = service.loginMethod(request); // ** want to await this

    Log.d(TAG, "FOURTH");

    // If login works, navigate to tabbed menu
    if (loginResponse.getAuthorized()) {
        Intent intent = new Intent(LoginActivity.this, SelectTeamActivity.class);
        startActivity(intent);
    }

    return loginResponse.getAuthorized();
}

LoginService.java LoginService.java

LoginResponse mLoginResponse = new LoginResponse();

public LoginResponse loginMethod(LoginRequest request) {
    try {
        String baseUrl = "https://myurl.com";
        // Create retrofit object
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();   //  This instantiates the Retrofit builder we will need for REST calls

        LoginEndpointInterface apiService = retrofit.create(LoginEndpointInterface.class);

        // Call the login method
        Observable<LoginResponse> call = apiService.login(request);

        Log.d(TAG, "SECOND");

        call.enqueue(new Callback<LoginResponse>() { // ** running as async
            @Override
            public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
                Log.d(TAG, "THIRD");

                int statusCode = response.code();

                // Login worked
                if (response.body().getAuthorized()) {
                    Log.d(TAG, "Login worked");
                    mLoginResponse = response.body();
                } else {
                    Log.d(TAG, "Login failed");
                }
            }

            @Override
            public void onFailure(Call<LoginResponse> call, Throwable t) {
                Log.d(TAG, "ERROR in web service call: " + t.toString());
            }
        });
    Log.d(TAG, "returning result of login check: " + result);
    } catch(Exception ex) {
        ex.printStackTrace();
    }

    return mLoginResponse;
}

Retrofit call interface 改造呼叫界面

public interface LoginEndpointInterface {

    @POST("api/login/")
    retrofit2.Call<LoginResponse> login(@Body LoginRequest body);

}

Thanks for the help! 谢谢您的帮助!

In android, networking or heavy tasks which block the ui can't be done on the main thread and hence all these things are done asynchronously. 在android中,无法在主线程上完成阻止ui的联网或繁重的任务,因此所有这些操作都是异步完成的。 To achieve what you are trying, you will need to call all your next steps after the network call is done, which can only be done in retrofit callback inside onResponse or onFailure . 为了实现您正在尝试的功能,您将需要在网络调用完成后调用所有后续步骤,这只能在onResponseonFailure内的改造回调中完成。 Its basically chaining of calls. 它基本上是呼叫链。 To make your code more readable, you can use your own interfaces for call back mechanisms or you can use libraries like RxJava which makes its really simple. 为了使代码更具可读性,您可以使用自己的接口来实现回调机制,也可以使用RxJava之类的库来简化代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM