【问题标题】:Good practice to process through sequence of Android volley requests通过 Android volley 请求序列处理的良好实践
【发布时间】:2018-03-22 13:42:35
【问题描述】:

我需要向服务器发送一系列请求。在控制台 Java 应用程序中执行此操作非常简单,因为它只是执行等待结果、评估结果、然后发出下一个请求的阻塞请求...

但是,我不知道如何最好地将其移植到 Android,因为我需要处理一系列操作,这些操作都在线程中处理,我无法“等待”它们完成。凌空代码很好,但是如果嵌套代码在嵌套代码中嵌套代码,结果将是一个巨大的块。

正常的顺序是:

  • 登录服务器(如果出现问题则停止)
  • 获取服务器状态
  • 根据状态获取更多数据。

在 Android 中,请求的代码现在如下所示:

        JsonObjectRequest jsonRequest = new JsonObjectRequest
            (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    try {
                        int myResult = response.getInt("result");
                        if (myResult!=0) {
                            throw new RuntimeException("Bad foo!");
                        } else {

                                  /* ...and here there's my problem. Here I would 
                                  normally create the next step (= the next  
                                  "jsonRequest = new JsonObjectRequest..." including the 
                                  entailed anonymous handler routine. But that would 
                                  lead to a giantly nested code. For you code-gurus: 
                                  How to solve that and still produce beautiful 
                                  readable code? */

                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {
                    error.printStackTrace();
                }
            });
    MyApplication.getInstance().getRequestQueue().add(jsonRequest);

另外:在控制台应用程序中,很容易将登录代码打包到一个函数中并为多种目的调用它。例如

private void RenameDaFiles() {
  LoginToServer();  // performs an internet request, in volley that starts a thread
  GetData();
  RenameFiles(); 
}

private void DeleteDaFiles() {
  LoginToServer();
  GetSomeOtherData();
  DeleteFiles(); 
}

使用 volley 我不能使用该程序方法,因为即使请求未完成,调用 volley 也会立即返回。我怎样才能做到最好?

提前非常感谢!

【问题讨论】:

  • 查看this 博客。你也可以使用反应式编程来做到这一点,检查this。
  • 感谢您对反应式编程的提示,这看起来很有希望。我会努力让事情顺利进行(对我来说需要大量阅读),如果我能取得一些成就,我会回到这里。

标签: android android-volley


【解决方案1】:

我也问过自己,这就是我的想法:我为请求链中的每个请求编写了一个私有方法。第一个方法在完成时调用第二个方法,在完成时调用第三个方法,依此类推。

最后一个方法调用每次传递给下一个方法的结果处理程序。

所以,实际上它的作用与嵌套匿名类的作用相同。但我认为它的可读性更好。

调用代码:

sendFirstRequest(new Consumer<JSONObject>() {
    @Override
    public void accept(JSONObject result) {

        Log.d(TAG, "accept: result = " + result);
    }
});

请求链:

private void sendFirstRequest(final Consumer<JSONObject> resultConsumer) {
    requestQueue.add(new JsonObjectRequest(
            Request.Method.GET,
            "www.google.de",
            null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {

                    sendSecondRequest(resultConsumer); // <-- chaining
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {

                }
            }
    ));
}

private void sendSecondRequest(final Consumer<JSONObject> resultConsumer) {
    requestQueue.add(new JsonObjectRequest(
            Request.Method.GET,
            "www.google.de",
            null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {

                    sendLastRequest(resultConsumer); // <-- chaining
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {

                }
            }
    ));
}

private void sendLastRequest(final Consumer<JSONObject> resultConsumer) {
    requestQueue.add(new JsonObjectRequest(
            Request.Method.GET,
            "www.google.de",
            null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {

                    resultConsumer.accept(response); // <-- final result
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {

                }
            }
    ));
}

每当我遇到“异步链问题”时,我都会使用该模式。

为了简化示例,我假设RequestQueue 被定义为一个字段。

另外,请注意像Consumer 这样的 Java 8 功能接口仅在 API 级别 24 之后才可用。但是,可以自己定义一个简单的版本:

public interface Consumer<T> {
    void accept(T t);
}

【讨论】:

    猜你喜欢
    • 2018-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多