Volley-POST/GET 参数

我看了谷歌 IO 2013年会议关于截击,我正在考虑转换到截击。Volley 是否支持向请求中添加 POST/GET 参数?如果是,我怎么做?

201888 次浏览

In your Request class (that extends Request), override the getParams() method. You would do the same for headers, just override getHeaders().

If you look at PostWithBody class in TestRequest.java in Volley tests, you'll find an example. It goes something like this

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 was kind enough to make a quick example project to show us how to use volley. https://github.com/evancharlton/folly/

For the GET parameters there are two alternatives:

First: As suggested in a comment bellow the question you can just use String and replace the parameters placeholders with their values like:

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

where num1 and num2 are String variables that contain your values.

Second: If you are using newer external HttpClient (4.2.x for example) you can use URIBuilder to build your Uri. Advantage is that if your uri string already has parameters in it it will be easier to pass it to the URIBuilder and then use ub.setQuery(URLEncodedUtils.format(getGetParams(), "UTF-8")); to add your additional parameters. That way you will not bother to check if "?" is already added to the uri or to miss some & thus eliminating a source for potential errors.

For the POST parameters probably sometimes will be easier than the accepted answer to do it like:

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

e.g. to just override the getParams() method.

You can find a working example (along with many other basic Volley examples) in the Andorid Volley Examples project.

CustomRequest is a way to solve the Volley's JSONObjectRequest can't post parameters like the StringRequest

here is the helper class which allow to add params:

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


}

thanks to Greenchiu

This helper class manages parameters for GET and POST requests:

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

This may help you...

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

Dealing with GET parameters I iterated on Andrea Motto' solution. The problem was that Volley called GetUrl several times and his solution, using an Iterator, destroyed original Map object. The subsequent Volley internal calls had an empty params object.

I added also the encode of parameters.

This is an inline usage (no subclass).

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

This function uses headers to pass an APIKEY and sets a TAG to the request useful to cancel it before its completion.

Hope this helps.

For Future Readers

I love to work with Volley. To save development time i tried to write small handy library Gloxey Netwok Manager to setup Volley with my project. It includes JSON parser and different other methods that helps to check network availability.

Use ConnectionManager.class in which different methods for Volley String and Volley JSON request are available. You can make requests of GET, PUT, POST, DELETE with or without header. You can read full documentation here.

Just put this line in your gradle file.

  dependencies {


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

Volley StringRequest

Method GET (without header)

    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.

Example

    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

Method POST/PUT/DELETE (without header)

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

Example

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

Bonus

Gloxey JSON Parser

Feel free to use gloxey json parser to parse your api response.

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

Example

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

To provide POST parameter send your parameter as JSONObject in to the JsonObjectRequest constructor. 3rd parameter accepts a JSONObject that is used in Request body.

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