我正在开发一个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
}
}
答案 0 :(得分: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一起使用。