Как получить асинхронный вызов для возврата ответа в основной поток, используя okhttp? - PullRequest
0 голосов
/ 02 мая 2018

Я пытаюсь сделать программу для Android, и я использую okhttp для json-вызовов. Я действительно хочу вернуть свой ответ за пределы темы, которую я создаю. Мне нужно создать поток для асинхронного вызова, в противном случае я получу исключение NetworkOnMainThreadException. Проблема в том, что я не могу получить строку ответа вне метода "onResponse", даже если мой responseString является глобальной переменной в классе. Поскольку он асинхронный, поток не запустится вовремя, чтобы получить мое значение в глобальной переменной, прежде чем он вернется. Как я могу убедиться, что получаю ответ, прежде чем он вернет мое значение responseString?

Вот мой код:

public static String getUserProductCategoriesFromServer(Activity activity, final String UID, final String EXPIRY, final String CLIENT, final String ACCESSTOKEN)
{
    activity.runOnUiThread(new Runnable()
    {
        @Override
        public void run()
        {
            final OkHttpClient client = new OkHttpClient();
            final Request request = new Request.Builder()
                    .url(JsonStorage.getJsonUserProductCategories())
                    .get()
                    .addHeader("access-token", ACCESSTOKEN)
                    .addHeader("client", CLIENT)
                    .addHeader("expiry", EXPIRY)
                    .addHeader("uid", UID)
                    .build();



            client.newCall(request).enqueue(new Callback()
            {
                @Override
                public void onFailure(Call call, IOException e)
                {

                }

                @Override
                public void onResponse(Call call, Response response) throws IOException
                {
                    try
                    {
                        response = client.newCall(request).execute();
                        String json = response.body().string();
                        JSONObject jsonObject = new JSONObject(json);
                        JSONArray jsonData = (JSONArray) jsonObject.getJSONArray("user_product_category_names");
                        responseString = jsonData.toString();
                        Log.v("TEST1", jsonData.toString()); //RETURNS JSON :D
                        Log.v("TEST2", responseString); //RETURNS JSON :D
                    } catch (IOException | JSONException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    });
    Log.v("TEST3", responseString); //RETURNS "NULL" :(
    return responseString;
}

1 Ответ

0 голосов
/ 02 мая 2018

Обычный способ получения результатов из асинхронного мира в синхронный (основанный на потоках) заключается в использовании Futures . Многие библиотеки реализуют такой интерфейс, например, Гуавы. Стандартная версия Java имеет реализацию с именем CompletableFuture . Он использует методы с разными именами и сигнатурами, но адаптер может быть легко реализован:

class CallbackFuture extends CompletableFuture<Response> implements Callback {
    public void onResponse(Call call, Response response) {
         super.complete(response);
    }
    public void onFailure(Call call, IOException e){
         super.completeExceptionally(e);
    }
}

Тогда вы можете использовать его следующим образом:

CallbackFuture future = new CallbackFuture();
client.newCall(request).enqueue(future);
Response response = future.get();

Имея Response, вы можете извлечь responseString так же, как вы это делали в первом варианте.

...