2016-12-21 234 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中使用此功能。