Java函数在函数执行之前返回一个值

时间:2019-04-29 09:17:17

标签: java android multithreading java-threads

我目前正在开发一个可访问在线API的android应用。我有一个专门用于此任务的类,另一个类仅使用从API检索的信息。问题是,当我调用API访问类时,它必须是异步的(由android studio定义),因此我使用了新的线程,但是当API访问类返回时,使用数据的类中的返回为null。好结果。

我已经尝试使用thread.join()将两个线程连接在一起,但是它不起作用。

这里是访问API访问类中的API的函数。最后的System.out可以按预期工作(我在控制台中看到了很好的结果)

Thread t = new Thread() {
            public void run() {
                try {
                    String url = "-----------------------------------------------"+id;
                    URL obj = new URL(url);
                    HttpURLConnection con = (HttpURLConnection) obj.openConnection();

                    con.setRequestMethod("GET");

                    con.setRequestProperty("x-api-key", "-------------------------------");
                    int responseCode = con.getResponseCode();

                    BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
                    String inputLine;
                    StringBuffer response = new StringBuffer();

                    while ((inputLine = in.readLine()) != null) {
                        response.append(inputLine);
                    }
                    in.close();
                    HttpRequest.retour = new JSONArray(response.toString());
                    System.out.println(HttpRequest.retour.toString());
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
        };
        t.start();

但是当我尝试在另一堂课中这样做时:

System.out.println(retour.toString());

我得到一个空指针异常,因为前一个方法的返回为空。

这是我的错?

2 个答案:

答案 0 :(得分:3)

这可能是因为您存在数据争用。 当您必须使用线程时,它们是并行执行的,在这种情况下,这意味着您的主线程在网络线程将响应写入对象之前就到达了System.out.println(retour.toString());
您必须找到一种同步它们的方法,以确保不会发生这种情况。
就像您在Android上一样,您可能想看看retrogradeOkHttp来抽象出这种低级功能。

答案 1 :(得分:2)

好吧,如果您使用单独的线程进行API调用,则不能期望在调用retour.toString()时完成该线程。将异步操作结果存储在静态字段中也是一个坏主意,因为它在多线程环境中不起作用。您可以尝试“完成未来”:

public CompletableFuture<String> callApi() {
    CompletableFuture<String> completableFuture  = new CompletableFuture<>();
    Executors.newCachedThreadPool().submit(() -> {
        // your api call
        completableFuture.complete(apiResult);
        return null;
    });
    return completableFuture;
}

//in other thread call future synchronously
String result = completableFuture.get();