同时AsyncTasks

时间:2016-12-21 16:01:25

标签: android android-asynctask okhttp okhttp3

我正在开发一个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 个答案:

答案 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一起使用。