如何返回对调用函数的响应? (Android应用通过JSON调用Java REST-Server) [英] How to return response to calling function? (Android-App calling Java REST-Server via JSON)

查看:107
本文介绍了如何返回对调用函数的响应? (Android应用通过JSON调用Java REST-Server)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Spring-Boot框架重写一些Android应用程序,以调用我用Java编写的REST服务器.

I'm rewriting some pieces of an Android App to call a REST-Server I've written in Java, using the Spring-Boot Framework.

总而言之,让我们在应用程序中说,函数A在我的MainController中调用了函数B(该B应该用于管理客户端与服务器之间的通信).函数B调用(还有一些额外的步骤)将调用我的服务器.当函数B进行调用时,它将使用匿名内部类重写方法来定义如何处理响应. 我很难从匿名内部类获得对函数B的响应,因此可以将其返回给函数A. 可悲的是,其中包含一些异步性,只是使事情变得更加有趣.

To summarize, let's say in the app, function A calls a function B in my MainController (which is supposed to manage the Client-Server Communication). Function B calls (with a few extra steps) calls my Server. When function B makes the call, it uses an anonymous inner class overriding a method to define how to handle the response. I struggle to get that response from the anonymous inner class to function B so it can be returned to function A. Sadly, some asynchronity is involved, just to make things that exta bit more interesting.

我的第一个尝试是使用一个Map,该Map用唯一的ID存储调用结果,以使其在内部类外部均可访问.理论上效果很好,但在异步下崩溃了

My first attempt was to use a Map that stores the call result with a unique ID to make it accessible outside the inner class. Works fairly well in theory, but crumbles under asyncronity

第二,我直言不讳地添加了一个循环,该循环应等待结果放入Map中再继续,以确保有返回值.

Secondly I bluntly added a loop that is supposed to wait for the result to be put in the Map before continuing, making sure there is something to return.

不知何故,循环没有正确执行(我相信),并且当我使用循环时,对服务器的调用永远不会结束(在没有循环的情况下会完成此操作)

Somehow, the loop isn't executed properly (I believe), and when I use the loop, the call to my server never finishes (which it does when there is no loop)

请参见以下代码

客户端:MainController

Client: MainController

class MainController
{
    private final AtomicLong counter;
    private final HashMap<Long, Object> callResults;

    public MainController(){
        counter = new AtomicLong();
        callResults  = new HashMap<>();
    }

    public Login getLoginByUsername(String username)
    {
        long callID = counter.incrementAndGet();
        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:");
                    callResults.put(callID, new CallResult(Login.parseFromJson(response)));
                    System.out.println(callResults.get(callID));

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });

        System.out.println("start waiting");
       while(callResults.get(callID) == null){
            System.out.print(".");
        }
        System.out.println("waiting over, return result:");
        System.out.println(callResults.get(callID));
        //return (Login) callResults.remove(callID).content;
        return null;
    }
}

客户端:ServerConnection

Client: ServerConnection

import com.loopj.android.http.*;
import cz.msebera.android.httpclient.HttpEntity;

public class ServerConnection {

    private static final String BASE_URL = "http://1.3.3.7:8080/";

    private static AsyncHttpClient client = new AsyncHttpClient();

    public static void get(String url, RequestParams params, JsonHttpResponseHandler responseHandler) {
        client.get(BASE_URL+url, params, responseHandler);
    }
}

这是我所知道的:

  1. 预期的响应最终会到来.当我不使用循环等待并仅返回null时,控制台将显示消息呼叫成功,输入结果:"和一个对象ID

  1. the intended response will come eventually. When I don't use the loop to wait and just return null, the console will display the messages "Call success, enter result:" and an Object-ID

在末尾使用while循环时,它永远不会输出". -它什么也没做.我知道该应用程序仍在运行,因为AndroidStudio不断在空间分配方面更新我的信息

When using the while-loop towards the end, it never prints "." - it just does nothing. I know the application is still running though, because AndroidStudio keeps updating me on space allocation

尝试应用观察者模式可能完全超出范围.我将不得不深入研究我不想接触的客户端代码.老实说,我提供的代码并不容易使用

Trying to apply an observer-pattern might is completely out of scope. I would have to dig really deep into client-sided code that I'd rather not touch. The code I was provided isn't exactly easy to work with to be honest

这是我假设的问题: 该循环阻止进行异步REST调用,从而使其无法终止.

This is, what I assume is the problem: The loop prevents the asynchronous REST-call to be made, thus making it impossible to terminate.

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

My question: A) How can I return the Login-Object I received from the server to the function that called the MainController.getLoginByUsername-function in the first place?

B)我试图用于等待的while循环是怎么回事?为什么不执行正文(print(".");),更重要的是,为什么它会阻止REST调用表单的执行/完成?

B) What's going on with the while-loop I attempted to use for waiting? Why won't the body (print(".");) be executed, and more importantly, why does it stop the REST-call form being executed / finished?

(也可以随时发表有关我的发帖风格的反馈,这是我第一次在这里提出问题)

(also feel free to leave feedback on my posting style, this is my first time asking a question here)

添加了问题B,可能会提供一种更简便的方法来找到快速解决方案

added question B, might provide an easier way to find a quick solution

编辑为UPDATE: 很抱歉,您的解释不够清楚:任何建议也需要我调整调用函数(例如LivedataRxjava等观察者模式,或者Leo Pelozo提供的其他非常好的建议)都是不可行的. 我至少测试了Leo Pelozos的建议,而底层代码根本不允许这样做.我无法访问参数,无法再使用函数返回. 我知道,对底层系统进行返工将是最好的方法,但是现在这根本超出了范围...

Edit to UPDATE: Sorry for not making this clear enough: any suggestion that needs me to adapt the calling function as well (e.g. Observer-Patterns like Livedata or Rxjava or the otherwise really good suggestions provided by Leo Pelozo) are not feasible. I tested at least Leo Pelozos suggestion, and the underlying code simply doesn't allow that. I lose access to parameters and can't utilize function returns any more. I know, that reworking the underlying system would be the best course of action, but right now that's simply out of scope...

推荐答案

感谢您的所有帮助!我找到了适合我情况的解决方案.

Thanks for all your help! I found a solution that works for my case.

首先,因为这只是一个原型,所以我实际上并不需要异步请求,因此我将ServerConnection改为使用SyncHttpClient:

First, as this is just a prototype, I don't really need my requests to be async, so I changed ServerConnection to use SyncHttpClient instead:

public class ServerConnection {

    private static final String BASE_URL = "http://10.203.58.11:8080/";

    private static SyncHttpClient client = new SyncHttpClient();

    public static void get(String url, RequestParams params, JsonHttpResponseHandler responseHandler) {
        client.get(getAbsoluteUrl(url), params, responseHandler);
    }
}

然后,Android不允许我在主线程上执行请求.这与AsyncHttpClient无关,因为异步部分是在其自己的线程中处理的.因此,我不得不在请求中添加线程.因此,我的MainController现在看起来像这样:

Then, Android won't allow me to perform requests on the main thread. This wasn't an issue with AsyncHttpClient, as the async-part is handled in a thread of its own. So I had to add threads to my requests. Thus, my MainController now looks something like this:

public class MainController
{
    private final AtomicLong counter;
    private final HashMap<Long, CallResult> callResults;

    public MainController(){
        counter = new AtomicLong();
        callResults  = new HashMap<>();
    }

public Login getLoginByUsername(String username)
    {
        long callID = counter.incrementAndGet();
        new Thread(new Runnable() {
            @Override
            public void run() {
                ServerConnection.get("person-login-relations?byUsername="+username,null, new JsonHttpResponseHandler(){
                    @Override
                    public void onSuccess(int statusCode, Header[] headers, JSONObject response){
                        try {
                            callResults.put(callID, new CallResult(Login.parseFromJson(response)));
                            System.out.println(callResults.get(callID));

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                });


            }
        })   .start();

        while(callResults.get(callID) == null){
            //wait
        }
        return (Login) callResults.remove(callID).content;
    }
}

我猜想我用来等待的while循环现在可以工作了,因为它没有阻塞负责执行和处理请求的线程.对此,我并不完全确定.

I guess the while-loop I use to wait now works because it's not blocking the thread that's responsible for performing and handling the request. Not entirely sure on that though.

诚然,这可能不是理想的解决方案,但鉴于我的具体情况,这是最可行的解决方案.

Admittedly, this may not be the ideal solution, but it's the most feasible given my specific context.

几个月后,我将负责重新开发我现在扩展的应用程序以连接到客户端.届时,我将确保落实您的大部分建议! 所以对任何阅读此解决方案的人来说:这是一种解决方法,因为我不需要异步请求,而且我不应该更改调用您在此处看到的方法的函数!我建议您仍然阅读其他答复,因为它们在质量上要好!

I a few months, I will be tasked to rework the application I'm now extending to connect to a client. At that point I will make sure to implement most of your suggestions! So to anyone reading this solution: this right here is a workaround because I don't require asynchronous requests and I'm not supposed to change the functions calling the methods you see here! I suggest you still read the other replies as they are qualitatively superior!

这篇关于如何返回对调用函数的响应? (Android应用通过JSON调用Java REST-Server)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆