排球-POST / GET参数


81

我看到了有关凌空的Google IO 2013会议,我正在考虑改用凌空。Volley是否支持添加POST / GET参数来请求?如果是,我该怎么办?


2
我没有看到整个主题演讲,但是我很确定仅通过将参数添加到URL中即可实现GET(例如http://example.com?param1=val1&param2=val2
JJJollyjim,

似乎尚无文档,但您可以在此处查看源代码android.googlesource.com/platform/frameworks/volley/+/master
MM。

@ JJ56-是的,但是POST参数呢?我看到了源代码,但未找到与POST参数相关的任何内容。
Ziem

1
这么说我很ham愧。但是,如果您到这里询问为什么您的请求在服务器上没有正文,请确保您使用的是POST / PUT方法。猜猜我只是累了。希望此评论可以帮助任何人或让我感觉更好
Alwin Kesler,

Answers:


64

在您的Request类(扩展Request)中,重写getParams()方法。您将对标头执行相同的操作,只是覆盖getHeaders()。

如果在Volley测试中查看TestRequest.java中的PostWithBody类,则会找到一个示例。像这样

public class LoginRequest extends Request<String> {

    // ... other methods go here

    private Map<String, String> mParams;

    public LoginRequest(String param1, String param2, Listener<String> listener, ErrorListener errorListener) {
        super(Method.POST, "http://test.url", errorListener);
        mListener = listener;
        mParams = new HashMap<String, String>();
        mParams.put("paramOne", param1);
        mParams.put("paramTwo", param2);

    }

    @Override
    public Map<String, String> getParams() {
        return mParams;
    }
}

埃文·查尔顿(Evan Charlton)很友善,他做了一个快速的示例项目,向我们展示了如何使用排球。 https://github.com/evancharlton/folly/


70
请注意,getParams(默认情况下)仅在POST或PUT请求中调用,在GET请求中调用。请参阅Ogre_BGR的答案
Itai Hanski

2
不敢相信我直到现在都没有注意到这一点
Afzal N

@AfzalivE,关于使用上述代码时如何使用OAuth签名API请求的任何想法?
Bipin Vayalu 2013年

2
@BipinVayalu如果您要连接到Google API,则应该可以使用com.android.volley.AndroidAuthenticator
Pierre-Antoine

您忘记了实例化mParam。
莫里茨

84

对于GET参数,有两种选择:

首先:正如在下面的注释中所建议的,您可以只使用String并将参数占位符替换为其值,例如:

String uri = String.format("http://somesite.com/some_endpoint.php?param1=%1$s&param2=%2$s",
                           num1,
                           num2);

StringRequest myReq = new StringRequest(Method.GET,
                                        uri,
                                        createMyReqSuccessListener(),
                                        createMyReqErrorListener());
queue.add(myReq);

其中num1和num2是包含您的值的String变量。

其次:如果您使用的是较新的外部HttpClient(例如4.2.x),则可以使用URIBuilder来构建Uri。优点是,如果您的uri字符串中已经包含参数,则将其传递给URIBuilder,然后用于ub.setQuery(URLEncodedUtils.format(getGetParams(), "UTF-8"));添加其他参数会更容易。这样,您就不必费心检查“?” 已添加到uri或错过了一些信息,从而消除了潜在错误的来源。

对于POST参数,有时可能会比接受的答案容易,例如:

StringRequest myReq = new StringRequest(Method.POST,
                                        "http://somesite.com/some_endpoint.php",
                                        createMyReqSuccessListener(),
                                        createMyReqErrorListener()) {

    protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {
        Map<String, String> params = new HashMap<String, String>();
        params.put("param1", num1);
        params.put("param2", num2);
        return params;
    };
};
queue.add(myReq);

例如只是重写getParams()方法。

您可以在Andorid Volley Examples项目中找到一个有效的示例(以及许多其他基本的Volley示例)。


我已经按照你的排球榜样。到目前为止,这是最有用的Volly代码,但是JsonObjectRequest中存在问题。我在createMyReqSuccessListener中得到了旧的响应,直到再次重新安装它为止。齐射是否将数据存储在缓存中?请提出一种方法。
SkyWalker

2
仅图像被缓存。请检查是否有某些代理正在拦截您的请求。如果请求具有完全相同的URL,并且代理很可能只是返回第一个结果。
Ognyan 2014年

2
Firefox有一个名为“ HTTP资源测试”的插件,该插件可让您再次向网络服务器发送请求。对于测试这样的案例非常有用。只需输入您的URL(以及POST参数(如果有)),然后查看服务器对多个连续请求的响应。如果再次得到相同的响应结果,则很有可能已缓存。在这种情况下,您可以检查返回的标头以检查是否存在代理标头。关于“不缓存”-是的,它应该可以工作。
Ognyan 2014年

2
我建议您打开一个单独的问题,以便其他人可以加入并提供帮助。请提供信息,说明您正在使用HURL或HttpClient使用哪种堆栈,同时还是要测试的android版本。请在此处添加新问题的链接,以便人们可以关注讨论。
Ognyan 2014年

3
@Yousif如果将其作为新问题提出,则可能会得到更好的答案,但总之:POST请求允许您发送不适合GET请求的文件和其他较大数据。使用GET请求时也存在安全风险,因为URL可能会记录在服务器上,从而暴露敏感数据。
Ognyan

23

CustomRequest是一种解决Volley的JSONObjectRequest无法发布参数的方法,例如 StringRequest

这是允许添加参数的帮助器类:

    import java.io.UnsupportedEncodingException;
    import java.util.Map;    
    import org.json.JSONException;
    import org.json.JSONObject;    
    import com.android.volley.NetworkResponse;
    import com.android.volley.ParseError;
    import com.android.volley.Request;
    import com.android.volley.Response;
    import com.android.volley.Response.ErrorListener;
    import com.android.volley.Response.Listener;
    import com.android.volley.toolbox.HttpHeaderParser;

    public class CustomRequest extends Request<JSONObject> {

    private Listener<JSONObject> listener;
    private Map<String, String> params;

    public CustomRequest(String url, Map<String, String> params,
            Listener<JSONObject> reponseListener, ErrorListener errorListener) {
        super(Method.GET, url, errorListener);
        this.listener = reponseListener;
        this.params = params;
    }

    public CustomRequest(int method, String url, Map<String, String> params,
            Listener<JSONObject> reponseListener, ErrorListener errorListener) {
        super(method, url, errorListener);
        this.listener = reponseListener;
        this.params = params;
    }

    protected Map<String, String> getParams()
            throws com.android.volley.AuthFailureError {
        return params;
    };

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

    @Override
    protected void deliverResponse(JSONObject response) {
        // TODO Auto-generated method stub
        listener.onResponse(response);
    }

}

感谢Greenchiu


@WarrenFaith感谢您指出,我已经更新了答案!
LOG_TAG 2013年

3
非常感谢,我在寻找此解决方案之前已经花了数小时的时间,这很奇怪,JSONObjectReuqestgetParams()函数覆盖无法正常工作。
Walid Ammar 2014年

@MohammadWalid仅供参考,请阅读此stackoverflow.com/questions/16902716/… 并尝试使用改造!凌空和改造都可以与okhttp一起使用!
LOG_TAG 2014年

我尝试了此解决方案,但对我没有用。getParams()不被调用。
Mahdi

10

此类帮助器类管理GETPOST请求的参数:

import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;    

import org.json.JSONException;
import org.json.JSONObject;

import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;

public class CustomRequest extends Request<JSONObject> {
    private int mMethod;
    private String mUrl;
    private Map<String, String> mParams;
    private Listener<JSONObject> mListener;

    public CustomRequest(int method, String url, Map<String, String> params,
            Listener<JSONObject> reponseListener, ErrorListener errorListener) {
        super(method, url, errorListener);
        this.mMethod = method;
        this.mUrl = url;
        this.mParams = params;
        this.mListener = reponseListener;
    }

@Override
public String getUrl() {
    if(mMethod == Request.Method.GET) {
        if(mParams != null) {
            StringBuilder stringBuilder = new StringBuilder(mUrl);
            Iterator<Map.Entry<String, String>> iterator = mParams.entrySet().iterator();
            int i = 1;
            while (iterator.hasNext()) {
                Map.Entry<String, String> entry = iterator.next();
                if (i == 1) {
                    stringBuilder.append("?" + entry.getKey() + "=" + entry.getValue());
                } else {
                    stringBuilder.append("&" + entry.getKey() + "=" + entry.getValue());
                }
                iterator.remove(); // avoids a ConcurrentModificationException
                i++;
            }
            mUrl = stringBuilder.toString();
        }
    }
    return mUrl;
}

    @Override
    protected Map<String, String> getParams()
            throws com.android.volley.AuthFailureError {
        return mParams;
    };

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

    @Override
    protected void deliverResponse(JSONObject response) {
        // TODO Auto-generated method stub
        mListener.onResponse(response);
    }
}

这解决了向GET方法添加参数的问题,谢谢!
pkarc

2
在我们的案例中,迭代器方法销毁了我们传递给函数的原始Map params对象。似乎Volley内部打GetUrl了几次电话。我们最终得到了经典的foreach方法,该方法在单独的答案中发布。希望这对谁登陆这里有所帮助。:)
Paolo Casciello '16

如何通过3个参数调用此帮助程序类以获取请求
kgandroid18'18

@kgandroid,使用您的键和值创建Map <String,String>。示例:Map <String,String>参数= new HashMap <String,String>(); params.put(“ param1”,“ value1”); params.put(“ param2”,“ value2”); params.put(“ param3”,“ value3”);
安德里亚·莫托

6

处理GET参数我在Andrea Motto的解决方案上进行了迭代。问题是Volley打电话给GetUrl了几次,而他的解决方案使用Iterator破坏了原始Map对象。随后的Volley内部调用具有一个空的params对象。

我还添加了参数编码。

这是内联用法(无子类)。

public void GET(String url, Map<String, String> params, Response.Listener<String> response_listener, Response.ErrorListener error_listener, String API_KEY, String stringRequestTag) {
    final Map<String, String> mParams = params;
    final String mAPI_KEY = API_KEY;
    final String mUrl = url;

    StringRequest stringRequest = new StringRequest(
            Request.Method.GET,
            mUrl,
            response_listener,
            error_listener
    ) {
        @Override
        protected Map<String, String> getParams() {
            return mParams;
        }

        @Override
        public String getUrl() {
            StringBuilder stringBuilder = new StringBuilder(mUrl);
            int i = 1;
            for (Map.Entry<String,String> entry: mParams.entrySet()) {
                String key;
                String value;
                try {
                    key = URLEncoder.encode(entry.getKey(), "UTF-8");
                    value = URLEncoder.encode(entry.getValue(), "UTF-8");
                    if(i == 1) {
                        stringBuilder.append("?" + key + "=" + value);
                    } else {
                        stringBuilder.append("&" + key + "=" + value);
                    }
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                i++;

            }
            String url = stringBuilder.toString();

            return url;
        }

        @Override
        public Map<String, String> getHeaders() {
            Map<String, String> headers = new HashMap<>();
            if (!(mAPI_KEY.equals(""))) {
                headers.put("X-API-KEY", mAPI_KEY);
            }
            return headers;
        }
    };

    if (stringRequestTag != null) {
        stringRequest.setTag(stringRequestTag);
    }

    mRequestQueue.add(stringRequest);
}

此函数使用标头传递APIKEY,并为请求设置TAG,以在完成之前取消该请求。

希望这可以帮助。


3

这可能对您有帮助...

private void loggedInToMainPage(final String emailName, final String passwordName) {

    String tag_string_req = "req_login";
    StringRequest stringRequest = new StringRequest(Request.Method.POST, "http://localhost/index", new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            Log.d(TAG, "Login Response: " + response.toString());
            try {
                JSONObject jsonObject = new JSONObject(response);
                Boolean error = jsonObject.getBoolean("error");
                if (!error) {

                    String uid = jsonObject.getString("uid");
                    JSONObject user = jsonObject.getJSONObject("user");
                    String email = user.getString("email");
                    String password = user.getString("password");


                    session.setLogin(true);
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);
                    finish();
                    Toast.makeText(getApplicationContext(), "its ok", Toast.LENGTH_SHORT).show();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {
            System.out.println("volley Error .................");
        }
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            Map<String, String> params = new HashMap<String, String>();
            params.put("tag", "login");
            params.put("email", emailName);
            params.put("password", passwordName);
            return params;
        }
    };


    MyApplication.getInstance().addToRequestQueue(stringRequest,tag_string_req);
}

3

给未来的读者

我喜欢和Volley合作。为了节省开发时间,我尝试编写方便的小型库Gloxey Netwok Manager,以在我的项目中设置Volley。它包括JSON解析器和其他有助于检查网络可用性的其他方法。

使用ConnectionManager.class其中提供用于Volley StringVolley JSON请求的不同方法。您可以带或不带标题的GET,PUT,POST,DELETE请求。您可以在此处阅读完整的文档

只需将此行放入gradle文件中即可。

  dependencies { 

       compile 'io.gloxey.gnm:network-manager:1.0.1'
   }

凌空StringRequest

GET方法(无标题)

    ConnectionManager.volleyStringRequest(context, isDialog, progressDialogView, requestURL, volleyResponseInterface);

如何使用?

     Configuration                Description

     Context                      Context 
     isDialog                     If true dialog will appear, otherwise not.
     progressView                 For custom progress view supply your progress view id and make isDialog true. otherwise pass null. 
     requestURL                   Pass your API URL.  
     volleyResponseInterface      Callback for response.  

    ConnectionManager.volleyStringRequest(this, false, null, "url", new VolleyResponse() {
    @Override
    public void onResponse(String _response) {

        /**
         * Handle Response
         */
    }

    @Override
     public void onErrorResponse(VolleyError error) {

        /**
         * handle Volley Error
         */
    }

    @Override
    public void isNetwork(boolean connected) {

        /**
         * True if internet is connected otherwise false
         */
    }
});

凌空StringRequest

方法POST / PUT / DELETE(无标题)

    ConnectionManager.volleyStringRequest(context, isDialog, progressDialogView, requestURL, requestMethod, params, volleyResponseInterface);

Use Method : Request.Method.POST
             Request.Method.PUT
             Request.Method.DELETE

Your params : 

HashMap<String, String> params = new HashMap<>();
params.put("param 1", "value");
params.put("param 2", "value");

ConnectionManager.volleyStringRequest(this, true, null, "url", Request.Method.POST, params, new VolleyResponse() {
    @Override
    public void onResponse(String _response) {

        /**
         * Handle Response
         */
    }

    @Override
    public void onErrorResponse(VolleyError error) {

        /**
         * handle Volley Error
         */
    }

    @Override
    public void isNetwork(boolean connected) {

        /**
         * True if internet is connected otherwise false
         */
    }
});

奖金

Gloxey JSON解析器

随时使用gloxey json解析器解析您的api响应。

  YourModel yourModel = GloxeyJsonParser.getInstance().parse(stringResponse, YourModel.class);

ConnectionManager.volleyStringRequest(this, false, null, "url", new VolleyResponse() {
    @Override
    public void onResponse(String _response) {

        /**
         * Handle Response
         */

         try {

          YourModel yourModel = GloxeyJsonParser.getInstance().parse(_response, YourModel.class);

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

    }

    @Override
     public void onErrorResponse(VolleyError error) {

        /**
         * handle Volley Error
         */
         if (error instanceof TimeoutError || error instanceof NoConnectionError) {

                showSnackBar(parentLayout, getString(R.string.internet_not_found), getString(R.string.retry), new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {

                     //handle retry button

                    }
                });

            } else if (error instanceof AuthFailureError) {
            } else if (error instanceof ServerError) {
            } else if (error instanceof NetworkError) {
            } else if (error instanceof ParseError) {
            }

    }

    @Override
    public void isNetwork(boolean connected) {

        /**
         * True if internet is connected otherwise false
         */
          if (!connected) {
                showSnackBar(parentLayout, getString(R.string.internet_not_found), getString(R.string.retry), new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        //Handle retry button
                    }
                });
    }
});


     public void showSnackBar(View view, String message) {
            Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
     }

     public void showSnackBar(View view, String message, String actionText, View.OnClickListener onClickListener) {
            Snackbar.make(view, message, Snackbar.LENGTH_LONG).setAction(actionText, onClickListener).show();
     }

但这是否支持Method.Get
David Kariuki


0

要提供POST参数,请将您的参数发送JSONObjectJsonObjectRequest构造函数中。第三个参数接受JSONObject在请求正文中使用的。

JSONObject paramJson = new JSONObject();

paramJson.put("key1", "value1");
paramJson.put("key2", "value2");


JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST,url,paramJson,
    new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {

        }
    },
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    });
requestQueue.add(jsonObjectRequest);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.