Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将响应返回到调用函数?(Android应用程序通过JSON调用Java REST服务器)_Java_Android_Rest_Spring Boot_Loopj - Fatal编程技术网

如何将响应返回到调用函数?(Android应用程序通过JSON调用Java REST服务器)

如何将响应返回到调用函数?(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

我正在重写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);
}
}
以下是我所知道的:

  • 预期的反应最终会出现。当我不使用循环等待并返回null时,控制台将显示消息“callsuccess,entresult:”和一个对象ID

  • 当使用while循环接近尾声时,它从不打印“.”-它只是什么都不做。我知道应用程序仍在运行,因为AndroidStudio不断更新我的空间分配

  • 尝试应用观察者模式可能完全超出范围。我必须深入研究客户端代码,我不想去碰它。老实说,提供给我的代码并不容易使用

  • 这就是,我认为问题在于: 循环阻止了异步REST调用,因此无法终止

    我的问题: A) 如何将从服务器收到的登录对象返回到调用MainController.getLoginByUsername-function的函数

    B) 我尝试用于等待的while循环发生了什么?为什么主体(
    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()
    。这将阻止用户界面并为用户提供糟糕的体验

    谢谢