如何将响应返回到调用函数?(Android应用程序通过JSON调用Java REST服务器)
我正在重写Android应用程序的一些部分,以调用我用Java编写的REST服务器,使用Spring Boot框架 总而言之,假设在应用程序中,函数A调用我的主控制器中的函数B(它应该管理客户机-服务器通信)。函数B调用(带有一些额外的步骤)调用我的服务器。当函数B进行调用时,它使用一个匿名内部类重写一个方法来定义如何处理响应。 我很难从匿名内部类得到函数B的响应,这样它就可以返回到函数A。 可悲的是,其中包含了一些异步性,只是为了让事情变得更有趣 我的第一次尝试是使用一个映射来存储具有唯一ID的调用结果,以便在内部类之外访问它。在理论上工作得相当好,但在异步下会崩溃 其次,我直截了当地添加了一个循环,该循环应该在继续之前等待结果放入映射,以确保有返回的内容 不知何故,循环没有正确执行(我相信),当我使用循环时,对我的服务器的调用永远不会完成(当没有循环时就会完成) 请参阅下面的代码 客户:主控制器如何将响应返回到调用函数?(Android应用程序通过JSON调用Java REST服务器),java,android,rest,spring-boot,loopj,Java,Android,Rest,Spring Boot,Loopj,我正在重写Android应用程序的一些部分,以调用我用Java编写的REST服务器,使用Spring Boot框架 总而言之,假设在应用程序中,函数A调用我的主控制器中的函数B(它应该管理客户机-服务器通信)。函数B调用(带有一些额外的步骤)调用我的服务器。当函数B进行调用时,它使用一个匿名内部类重写一个方法来定义如何处理响应。 我很难从匿名内部类得到函数B的响应,这样它就可以返回到函数A。 可悲的是,其中包含了一些异步性,只是为了让事情变得更有趣 我的第一次尝试是使用一个映射来存储具有唯一ID
class主控制器
{
专用最终原子计数器;
私有最终HashMap调用结果;
公共主控制器(){
计数器=新的原子长();
callResults=newhashmap();
}
公共登录名getLoginByUsername(字符串用户名)
{
long callID=counter.incrementAndGet();
System.out.println(“启动调用”);
get(“myURL”,null,新的JsonHttpResponseHandler(){
@凌驾
成功时的公共void(int statusCode,Header[]headers,JSONObject响应){
试一试{
System.out.println(“调用成功,输入结果:”);
put(callID,newcallresult(Login.parseFromJson(response));
System.out.println(callResults.get(callID));
}捕获(JSONException e){
e、 printStackTrace();
}
}
});
System.out.println(“开始等待”);
while(callResults.get(callID)==null){
系统输出打印(“.”);
}
System.out.println(“等待,返回结果:”);
System.out.println(callResults.get(callID));
//返回(登录)callResults.remove(callID.content;
返回null;
}
}
客户端:服务器连接
import com.loopj.android.http.*;
导入cz.msebera.android.httpclient.HttpEntity;
公共类服务器连接{
私有静态最终字符串BASE_URL=”http://1.3.3.7:8080/";
私有静态AsyncHttpClient=新的AsyncHttpClient();
公共静态void get(字符串url、RequestParams参数、JsonHttpResponseHandler响应Handler){
get(BASE_URL+URL,params,responseHandler);
}
}
以下是我所知道的:
print(“.”;
)不会被执行,更重要的是,为什么它会停止正在执行/完成的REST调用表单
(也请随时就我的发帖风格留下反馈,这是我第一次在这里提问)
编辑:添加问题B,可能提供一种更简单的方法来快速找到解决方案
编辑以更新:
很抱歉,我没有说清楚:任何需要我调整调用函数的建议(例如Livedata
或Rxjava
之类的观察者模式,或者Leo Pelozo提供的其他非常好的建议)都是不可行的。
我至少测试了Leo Pelozos的建议,而底层代码根本不允许这样做。我无法访问参数,无法再使用函数返回。
我知道,改造底层系统将是最好的做法,但现在这完全超出了范围…你是否使用过谷歌的GSON,它将JSON对象转换为java对象,它的语法很简单,你会喜欢它,我一直在使用它。我使用截击来响应HTTP请求。 就像使用GSON一样
GSON gson = new GSON();
LoginObject login = new LoginObject();
login=gson.fromJson(responce,LoginObject.class);
瞧,你完成了。如果你不想使用
Livedata
或Rxjava
,你可以重构该方法以接受JsonHttpResponseHandler
或自定义回调,它并不漂亮,但可以工作:
一,
然后这样称呼它:
getLoginByUsername("myUsername", new JsonHttpResponseHandler(){
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response){
try {
Login myLogin = Login.parseFromJson(response);
//do stuff
} catch (JSONException e) {
e.printStackTrace();
}
}
});
MainController controller = new MainController();
controller.getLoginByUsername("myUsername", new MainController.OnLogin() {
@Override
public void onSuccessLogin(Login login) {
//do whatever here
}
});
public CompletableFuture<Login> loginByUsername(String username) {
CompletableFuture<Login> promise = new CompletableFuture<Login>();
System.out.println("Start call");
ServerConnection.get("myURL",null, new JsonHttpResponseHandler(){
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response){
try {
System.out.println("Call success, enter result:");
promise.complete(Login.parseFromJson(response));
} catch (JSONException e) {
promise.completeExceptionally(e);
}
}
});
return promise;
}
Login login = loginByUsername("user").get();
// Or wait a maximum time
Login login = loginByUsername("user").get(30, TimeUnit.SECONDS);
或
二,
您可以使用
CompletableFuture
轻松实现这一点。它的工作原理类似于JavaScript中的承诺。如果在API级别24之前需要兼容性,请检查
因此,您的getLoginByUsername
将如下所示:
getLoginByUsername("myUsername", new JsonHttpResponseHandler(){
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response){
try {
Login myLogin = Login.parseFromJson(response);
//do stuff
} catch (JSONException e) {
e.printStackTrace();
}
}
});
MainController controller = new MainController();
controller.getLoginByUsername("myUsername", new MainController.OnLogin() {
@Override
public void onSuccessLogin(Login login) {
//do whatever here
}
});
public CompletableFuture<Login> loginByUsername(String username) {
CompletableFuture<Login> promise = new CompletableFuture<Login>();
System.out.println("Start call");
ServerConnection.get("myURL",null, new JsonHttpResponseHandler(){
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response){
try {
System.out.println("Call success, enter result:");
promise.complete(Login.parseFromJson(response));
} catch (JSONException e) {
promise.completeExceptionally(e);
}
}
});
return promise;
}
Login login = loginByUsername("user").get();
// Or wait a maximum time
Login login = loginByUsername("user").get(30, TimeUnit.SECONDS);
永远不要在UIThread上调用get()
。这将阻止用户界面并为用户提供糟糕的体验谢谢