我目前正在开发一个访问在线API的Android应用程序。我有一个专门用于此任务的类,另一个类只使用从API检索的信息。问题是当我调用API访问类时,它必须是异步的(由android studio定义)所以我使用了一个新的Thread,但是当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());
我得到一个空指针异常,因为前一个方法的返回值为null。
我的错在哪里?
这可能是因为您有数据竞争。当你必须并行执行线程时,在这种情况下意味着你的主线程在网络线程将响应写入对象之前到达System.out.println(retour.toString());
。
您必须找到一种方法来同步它们以确保不会发生这种情况。
看到你在Android上,你可能想看看retrograde和OkHttp来抽象这个低级功能。
好吧,如果您使用单独的线程进行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();