如何使用okhttp进行异步调用以将响应返回到主线程? [英] How to get async call to return response to main thread, using okhttp?

查看:219
本文介绍了如何使用okhttp进行异步调用以将响应返回到主线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为Android编写程序,并且我使用okhttp进行json调用.我真的很想将我的回复返回到我正在创建的线程之外.我需要为异步调用创建线程,否则我将收到NetworkOnMainThreadException.问题是,即使我的responseString是类中的全局变量,我的响应字符串似乎也无法从"onResponse"方法之外获取.由于它是异步的,因此在返回之前,该线程将无法及时运行以在全局变量中获取我的值.在返回responseString值之前,如何确保获得响应?

I'm trying to make a program for Android, and I'm using okhttp for json-calls. I really want to return my response to the outside of the thread I'm creating. I need to create the thread for an async call otherwise I'll get a NetworkOnMainThreadException. Problem is that I can't seem to get my response string outside the "onResponse" method, even though my responseString is a global variable in the class. Since it's async, the thread won't run in time to get my value in the global variable before it returns. How can I make sure I get the response, before it returns my responseString value?

这是我的代码:

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;
}

推荐答案

从异步世界获取结果到同步(基于线程)的常见方法是使用 CompletableFuture 的实现.它使用具有不同名称和签名的方法,但是可以轻松实现适配器:

Common way to get results from asynchronous world to synchronous (thread-based) is to use Futures. Many libraries implement such an interface, e.g. Guava. Standard java has implementation named CompletableFuture. It uses methods with different names and signatures, but an adapter can be easily implemented:

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);
    }
}

然后您可以按以下方式使用它:

Then you can use it as follows:

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

具有 Response ,您可以像在第一个变体中一样提取 responseString .

Having the Response, you can extract responseString the same way as you did it in the your first variant.

这篇关于如何使用okhttp进行异步调用以将响应返回到主线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆