我目前正在开发一个可访问在线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());
我得到一个空指针异常,因为前一个方法的返回为空。
这是我的错?
答案 0 :(得分:3)
这可能是因为您存在数据争用。
当您必须使用线程时,它们是并行执行的,在这种情况下,这意味着您的主线程在网络线程将响应写入对象之前就到达了System.out.println(retour.toString());
。
您必须找到一种同步它们的方法,以确保不会发生这种情况。
就像您在Android上一样,您可能想看看retrograde和OkHttp来抽象出这种低级功能。
答案 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();