2016-12-21 194 views
0

我正在开发一个android应用程序,它必须对服务器执行多个并发http请求,所以我决定使用okhttp库来提出请求。同步异步任务

问题是,当我尝试同时发出某些请求时,我必须等到第一次完成时才执行以下操作。

我创建并运行从我调用以下方法AsyncTasks:

public class ApiRestClient { 

    public static void get(String url, Map<String, String> params, Api.ApiCallback callback) { 
     OkHttpClient client = new OkHttpClient.Builder() 
       .connectTimeout(15, TimeUnit.SECONDS) 
       .readTimeout(60, TimeUnit.SECONDS).build(); 

     try { 
      HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder(); 
      for (Map.Entry<String, String> e : params.entrySet()) { 
       builder.addQueryParameter(e.getKey(), e.getValue()); 
      } 

      Request request = new Request.Builder() 
        .url(builder.build()) 
        .get() 
        .build(); 

      Response response = client.newCall(request).execute(); 
      if (response.code() == HttpURLConnection.HTTP_OK) { 
       JSONObject data = new JSONObject(response.body().string()); 
       if (callback != null) { 
        try { 
         try { 
          callback.onSuccess(data); 
         } catch (JSONException ex){ 
          throw new ApiException(data, ex); 
         } 
        } catch (ApiException ex) { 
         callback.onFail(ex); 
        } 
       } 
      } else { 
       if (callback != null) { 
        callback.onFail(new ApiException(response.code())); 
       } 
      } 
     } catch (JSONException | IOException e) { 
      Log.e(ApiRestClient.class.getSimpleName(), "ApiRestClient.get", e); 
      if (callback != null) { 
       callback.onFail(new ApiException(ApiException.SC_INTERNAL_SERVER_ERROR,e)); 
      } 
     } 
    } 

    public static void post(String url, Map<String, String> params, Api.ApiCallback callback) { 
     try { 
      OkHttpClient client = new OkHttpClient.Builder() 
        .connectTimeout(15, TimeUnit.SECONDS) 
        .readTimeout(60, TimeUnit.SECONDS).build(); 

      HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder(); 

      FormBody.Builder formBuilder = new FormBody.Builder(); 
      for (Map.Entry<String, String> e : params.entrySet()) { 
       formBuilder.add(e.getKey(), e.getValue()); 
      } 

      RequestBody body = formBuilder.build(); 
      Request request = new Request.Builder() 
        .url(builder.build()) 
        .post(body) 
        .build(); 

      Response response = client.newCall(request).execute(); 
      if (response.code() == HttpURLConnection.HTTP_OK) { 
       JSONObject data = new JSONObject(response.body().string()); 
       if (callback != null) { 
        try { 
         callback.onSuccess(data); 
        } catch (ApiException ex){ 
         callback.onFail(ex); 
        } 
       } 
      } else { 
       if (callback != null) { 
        callback.onFail(new ApiException(response.code())); 
       } 
      } 
     } catch (JSONException | IOException e) { 
      Log.e(ApiRestClient.class.getSimpleName(), "ApiRestClient.post", e); 
      if (callback != null) { 
       callback.onFail(new ApiException(HttpURLConnection.HTTP_INTERNAL_ERROR,e)); 
      } 
     } 
    } 
} 

这是的AsyncTask代码:

public class ApiMethods extends AsyncTask<String, Integer, Boolean> { 

    private RequestMethod requestMethod; 
    private String serverURL; 
    private Api.ApiCallback callback; 
    private Map<String, String> requestParams; 
    public ApiMethods(RequestMethod requestMethod, String serverURL, Map<String, String> requestParams, Api.ApiCallback callback) { 
     this.requestMethod = requestMethod; 
     this.serverURL = serverURL; 
     this.callback = callback; 
     this.requestParams = requestParams; 
    } 

    @Override 
    protected Boolean doInBackground(String... params) { 
     switch (this.requestMethod) { 
      case GET: 
       ApiRestClient.get(serverURL, requestParams, callback); 
       break; 

      case POST: 
       ApiRestClient.post(serverURL, requestParams, callback); 
       break; 

      default: 
       break; 
     } 

     return true; 
    } 

    public enum RequestMethod { 
     GET, POST 
    } 
} 

回答

1

AsyncTask文档:

当首先介绍,AsyncTasks在单个后台线程上被串行执行。从DONUT开始,将其更改为允许多个任务并行操作的线程池。从HONEYCOMB开始,任务在单个线程上执行,以避免并行执行导致的常见应用程序错误。

如果您真的想要并行执行,您可以调用executeOnExecutor(java.util.concurrent.Executor, Object[])THREAD_POOL_EXECUTOR

所以,如果你有

 ApiMethods apiMethods = new ApiMethods(); 

变化

 apiMethods.execute(params); 

 apiMethods.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); 

executeOnExecutor DOC:

警告:允许多个任务从线程池并行运行通常不是人们想要的,因为它们的操作顺序未定义。例如,如果这些任务用于修改任何共同的状态(例如由于按钮点击而写入文件),则不能保证修改的顺序。如果没有仔细的工作,极少数情况下,较旧版本的数据可能会被较旧版本覆盖,从而导致数据丢失和稳定性问题。这种变化最好是连续执行;为了保证这些工作被序列化,无论平台版本如何,您都可以在SERIAL_EXECUTOR中使用此功能。