Volley - POST/GET 参数

Posted

技术标签:

【中文标题】Volley - POST/GET 参数【英文标题】:Volley - POST/GET parameters 【发布时间】:2013-05-13 14:59:31 【问题描述】:

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

【问题讨论】:

我没有看到完整的主题演讲,但我很确定只需将参数添加到 URL(例如http://example.com?param1=val1&param2=val2),GET 应该是可行的 好像还没有文档,不过你可以在这里查看源代码android.googlesource.com/platform/frameworks/volley/+/master @JJ56 - 对,但是 POST 参数呢?我看到了源代码,但没有找到任何与 POST 参数相关的内容。 我很惭愧地说这个。但是,如果您在这里询问为什么您的请求在您的服务器上没有正文,请确保您使用的是 POST/PUT 方法。我想我只是累了。希望这条评论可以帮助任何人或帮助我感觉更好 【参考方案1】:

对于 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 是包含您的值的字符串变量。

第二:如果您使用newer external 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 project 中找到一个工作示例(以及许多其他基本 Volley 示例)。

【讨论】:

我已经关注了你的 Volley 示例。到目前为止,它是最有用的 Volly 代码,但我在 JsonObjectRequest 中有一个问题。在我重新安装之前,我在 createMyReqSuccessListener 中得到了旧的响应。凌空将数据存储在缓存中吗?请提出一种方法来做到这一点。 只缓存图片。请检查是否有一些代理正在拦截您的请求。如果请求具有完全相同的 URL,并且代理可能只是返回第一个结果。 Firefox 有一个名为“HTTP 资源测试”的插件,允许您再次向 Web 服务器发送请求。对于这样的测试用例非常有用。只需输入您的 URL(和 POST 参数,如果有),然后查看服务器对多个连续请求的响应是什么。如果再次获得相同的响应结果,很可能会被缓存。在这种情况下,您可以检查返回的标头以检查是否有代理标头。关于“无缓存” - 是的,它应该可以工作。 我建议您打开单独的问题,以便其他人可以加入并提供帮助。请提供您使用 HURL 或 HttpClient 的堆栈信息,以及您正在测试的 android 版本。请在此处添加指向新问题的链接,以便人们关注讨论。 @Yousif 如果您将此作为新问题提出,您可能会得到更好的答案,但简而言之:POST 请求允许您发送不适合 GET 请求的文件和其他更大的数据。使用 GET 请求时也存在安全风险,因为 URL 可能 会被记录在服务器上,从而暴露敏感数据。【参考方案2】:

在您的 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 非常友好地制作了一个快速示例项目,向我们展示了如何使用 volley。 https://github.com/evancharlton/folly/

【讨论】:

请注意,getParams 仅在(默认情况下)在 POST 或 PUT 请求中调用,而不是在 GET 请求中调用。查看 Ogre_BGR 的回答 不敢相信直到现在我才注意到这一点 @AfzalivE,您知道在使用上述代码时如何使用 OAuth 签署 API 请求吗? @BipinVayalu 如果您连接到 Google API,您应该能够使用 com.android.volley.AndroidAuthenticator 您忘记实例化 mParams。【参考方案3】:

CustomRequest是解决Volley的JSONObjectRequest不能像StringRequest这样的post参数

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

    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 感谢您指出,我已经更新了答案! 非常感谢,我在找到这个解决方案之前已经搜索了几个小时,JSONObjectReuqest getParams() 函数覆盖不起作用真是太奇怪了。 @MohammadWalid 仅供参考阅读此***.com/questions/16902716/… 并尝试使用改造! okhttp 可以使用volley 和retrofit ! 我尝试了这个解决方案,但对我不起作用。未调用 getParams()。【参考方案4】:

这个帮助类管理 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方法中添加参数,谢谢! 在我们的例子中,迭代器方法破坏了我们传递给函数的原始 Map 参数对象。似乎 Volley 在内部多次调用 GetUrl。我们最终得到了一个经典的 foreach 方法,如在单独的答案中发布的那样。希望这对登陆这里的人有所帮助。 :) 如何调用这个帮助类来获取 3 个参数的请求 @kgandroid,使用您的键和值创建一个 Map。示例: Map params = new HashMap(); params.put("param1", "value1"); params.put("param2", "value2"); params.put("param3", "value3");【参考方案5】:

处理 GET 参数我在 Andrea Motto 的解决方案中进行了迭代。 问题是 Volley 多次调用 GetUrl 并且他的解决方案使用迭代器破坏了原始 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,以便在完成之前取消它。

希望这会有所帮助。

【讨论】:

【参考方案6】:

这可能对你有帮助...

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);

【讨论】:

【参考方案7】:

面向未来的读者

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

使用ConnectionManager.class,其中提供了Volley StringVolley JSON 请求的不同方法。 您可以发出 GET、PUT、POST、DELETE 请求,带或不带标头。你可以阅读完整的文档here。

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

  dependencies  

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

Volley StringRequest

方法 GET(无标题)

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

How to use?

     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
         */
    
);

Volley 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 Parser

随意使用 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 是的,请查看详细信息。 github.com/adnanbinmustafa/Gloxey-Network-Manager【参考方案8】:

要提供POST 参数,请将您的参数作为JSONObject 发送到JsonObjectRequest 构造函数。第三个参数接受在请求正文中使用的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);

【讨论】:

以上是关于Volley - POST/GET 参数的主要内容,如果未能解决你的问题,请参考以下文章

volle介绍02

您如何使用 Android Volley API?

get请求和post请求区别

Volley 没有通过参数?

Android Volley 如何使用 volley 在 POST 请求中发送用户名和密码以及其他参数

删除带有标头和参数的请求 Volley