【问题标题】:Return value from inner class in a method从方法中的内部类返回值
【发布时间】:2016-02-08 16:42:55
【问题描述】:

我正在为 Android 应用构建登录系统。我正在使用OkHttp 连接到我的服务器并获得 JSON 响应。

我已经定义了一个带有登录返回数据的类(现在只是根据用户是否存在于数据库中的真假响应),然后编写连接服务器的代码,如下所示:

class UserLogin {
    boolean status;

    public void setStatus(boolean status) {
        this.status = status;
    }

    public boolean getStatus() {
        return status;
    }
}

public class ClientServerInterface {

    OkHttpClient client = new OkHttpClient();

    boolean login(Request request) {
        final Gson gson = new Gson();
        client.newCall(request).enqueue(new Callback() {
            UserLogin login;
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                login = gson.fromJson(response.body().charStream(), UserLogin.class);
                login.setStatus(login.status);
            }
        });
        // need to return the boolean response (status) here
    }
}

Request 变量传递给login 方法的代码运行良好。我希望 login 返回一个布尔响应,以便我可以将其传递给其他类中的其他方法。

但是,因为UserLogin 对象是在callback 中定义的,所以我无法在父方法中访问它。我制作了一个getStatus 方法,但不确定如何正确使用它来获取主要login 方法中的状态。

【问题讨论】:

  • // need to return the boolean response (status) here => 显然你不能这样做......因为当这个方法返回时,请求可能仍在运行

标签: java android json http callback


【解决方案1】:

将 Request 变量传递给 login 方法的代码有效 完美。我想登录返回一个布尔响应,以便我可以 将其传递给其他类中的其他方法。

你不能。 enqueue 以异步方式执行代码。您不知道何时调用回调。您可以做的是将回调作为参数添加到您的登录方法。例如

 boolean login(Request request, final Callback callback) {

然后将其传递给enqueue

client.newCall(request).enqueue(callback);

或手动调用回调。例如

@Override
public void onResponse(Call call, Response response) throws IOException {
      if (callback != null) {
           callback.onResponse(call, response);
      }
}

在这两种情况下,login 的调用者都会收到对提供的对象的回调,并根据它收到的内容,决定采取什么行动

【讨论】:

    【解决方案2】:

    您可以使用SynchronousQueue

    final SynchronousQueue<Boolean> queue = new SynchronousQueue<>();
    client.newCall(request).enqueue(new Callback() {
            UserLogin login;
            @Override
            public void onFailure(Call call, IOException e) {
              queue.put(false);
            }
    
            @Override
            public void onResponse(Call call, Response response) throws IOException {
              queue.put(true);
            }
        });
    return queue.take();
    

    【讨论】:

    • @Selvin 这更像是对 OP 的问题/要求的评论,而不是我的回答。
    • @AndyTurner 感谢您的回答。 @selvin/Andy,我从答案中假设我做得不太对。如果您能提出更好的方法来重新编写我的代码以使其正常工作,那就太好了。本质上,我只需要获取 status 变量 - 如果 login 方法没有返回任何内容,那很好。谢谢!
    • @TomOakley Selvin(我认为)说您实际上应该有一个回调,以便您可以在请求完成后采取一些行动。该回调应作为参数传递给login 方法,例如void login(Request request, Callback onRequestComplete) {
    【解决方案3】:

    将 loginStatus 变量添加到如下类中,再添加一个以指示登录操作完成。

    public class ClientServerInterface {
    
        OkHttpClient client = new OkHttpClient();
        private  boolean loginStatus = false;
        private boolean isLoginOperationDone = false;
        boolean login(Request request) {
            final Gson gson = new Gson();
            client.newCall(request).enqueue(new Callback() {
                UserLogin login;
                @Override
                public void onFailure(Call call, IOException e) {
    
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    login = gson.fromJson(response.body().charStream(), UserLogin.class);
                    loginStatus = login.setStatus(login.status);
                    isLoginOperationDone = true;
                }
            });
            // need to return the boolean response (status) here
            while( !isLoginOperationDone )
            {
               //not to do anything.
            }
            return loginStatus;
        }
    }
    

    请注意,这可能有点老套,但确实可以解决您的问题。

    【讨论】:

      【解决方案4】:

      要走的路是使用 AsyncTask。重写 doInBackground 方法执行 http 请求并通过重写 onPostExecute 方法获取结果。

      在此处阅读更多信息:http://developer.android.com/reference/android/os/AsyncTask.html

      更好的方法是为所有 API 调用运行后台服务。

      【讨论】:

      • 对不起,先生,但他没有使用 AsyncTask。另外,我建议改用 Service,但我发现它比简单的 AsyncTask 需要更多的工作。
      猜你喜欢
      • 2023-03-10
      • 1970-01-01
      • 2022-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-12
      • 1970-01-01
      相关资源
      最近更新 更多