【问题标题】:retrofit invoking asynchronous call synchronously改造同步调用异步调用
【发布时间】:2016-03-24 17:51:41
【问题描述】:

这看起来很奇怪,但我最终陷入了这种情况。使用 Retrofit 异步实现 Restful API 调用。现在有一个突然的需求变化,必须一个接一个地调用 API(一次一个),所以在第二个 API 调用中,我必须发送从前一个响应接收到的会话令牌。一种方法是使每个 API 调用都同步,但实现此更改需要时间。

我试过了:

  1. setExecutor(Executors.newSingleThreadExecutor(),new MainThreadExecutor) 用于RestAdapter.Builder。这不起作用 因为 API 调用是异步的,并且在获得响应之前 进行了先前的 API 调用第二次调用。所以第二个请求有 无效的会话令牌。

  2. 在我实现了所有 Restful Web 服务的课堂上, 使用 Executors.newSingleThreadExecutor() ,这也没有用 出于同样的原因。

    任何人都可以建议如何通过最小的更改来解决此问题。
    Webservice Manager如下,这是部分的,还有很多类似登录的api:

public class WebServiceManager {
    private static final String ROOT_PATH = Urls.REST_ROOT_URL;
    RestAdapter restAdapter;
    WebServiceInterface webServiceInterface;
    private String requestKey;
    private String sessionId;
    private Context context;

    public WebServiceManager(Context context) {
        this.context = context;
        initializeWebServiceAdapter();
    }

    private void initializeWebServiceAdapter() {
        restAdapter = new RestAdapter.Builder()
                .setEndpoint(ROOT_PATH)
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .build();
        webServiceInterface = restAdapter.create(WebServiceInterface.class);
    }

    private void setHeaderValues(BaseModel model) {
     SessionManager sm=  context.getApplicationContext().getSessionManager();
        model.getRequestHeader().setRequestKey(sm.getRequestKey());
        model.getRequestHeader().setSessionId(sm.getSessionId());
    }

    public void login(String emailID, String passwd, final WebServiceCallback loginModelWebServiceCallback) {
        LoginModel model = RestRequest.getLoginModel(emailID, passwd);
        setHeaderValues(model);
            webServiceInterface.login(model, new Callback() {
                @Override
                public void success(LoginModel loginModel, Response response) {
                    if (loginModelWebServiceCallback != null)
                    {
                        SessionManager sm=  context.getApplicationContext().getSessionManager();
                        sm.setSessionDetails(response.getRequestKey(),response.getSessionId());
                        loginModelWebServiceCallback.success(loginModel);
                    }
                }

                @Override
                public void failure(RetrofitError error) {
                    if (loginModelWebServiceCallback != null)
                        loginModelWebServiceCallback.failure(error);
                }
            });
        } 

}

【问题讨论】:

  • 你调用了两个API吧?
  • 所以,在得到第一个 API 的响应后调用第二个 API。
  • 是的,还有更多方法引用的代码是部分的
  • 从第一个 API 获得响应后调用第二个 API。
  • 但要做到这一点,我必须做很多更改并且需要维护一些队列,不是吗?

标签: java android retrofit synchronous


【解决方案1】:

当第二个 api 调用需要一些参数时,可以在第一个 API 本身的响应中发出请求。看看样本:

public void login(String emailID, String passwd, final WebServiceCallback loginModelWebServiceCallback) {
    LoginModel model = RestRequest.getLoginModel(emailID, passwd);
    setHeaderValues(model);
    webServiceInterface.login(model, new Callback() {
      @Override
      public void success(LoginModel loginModel, Response response) {
        if (loginModelWebServiceCallback != null) {
          makeSecondAPIcall();
        }
      }

      @Override
      public void failure(RetrofitError error) {
        if (loginModelWebServiceCallback != null)
          loginModelWebServiceCallback.failure(error);
      }
    });
  }

【讨论】:

    【解决方案2】:

    Executor 无关紧要,因为您总是使用 Callback 参数调用 Retrofit 服务,这使得它是异步的。如果您希望 Retrofit 调用是同步的,那么服务调用方法需要返回类型,而不是 void。您可以在文档中阅读此内容。

    一旦您使 API 调用同步并按照您的需要排序,您可以将它们包装在 Runnable 中并让 Executor 为您处理线程。

    【讨论】:

    • 这是唯一的解决方案吗?在这种情况下我需要做很多代码重构,所以寻找替代解决方案。
    猜你喜欢
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 2013-07-12
    相关资源
    最近更新 更多