通过Android排球请求序列处理的好习惯

时间:2018-03-22 13:42:35

标签: android android-volley

我需要向服务器发送一系列请求。在控制台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返回。我该如何做到最好?

提前多多感谢!

1 个答案:

答案 0 :(得分: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);
}