我看到了关于 Volley 的 Google IO 2013 会议,我正在考虑改用 volley。Volley 是否支持在请求中添加 POST/GET 参数?如果是,我该怎么做?
8 回答
对于 GET 参数,有两种选择:
首先:正如问题下方的评论中所建议的,您可以使用 String 并将参数占位符替换为它们的值,例如:
String uri = String.format("http://somesite.com/some_endpoint.php?param1=%1$s¶m2=%2$s",
num1,
num2);
StringRequest myReq = new StringRequest(Method.GET,
uri,
createMyReqSuccessListener(),
createMyReqErrorListener());
queue.add(myReq);
其中 num1 和 num2 是包含您的值的字符串变量。
第二:如果您使用较新的外部 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 示例)。
在您的 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/
CustomRequest 是解决 Volley 的 JSONObjectRequest 不能 post 参数之类的方法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);
}
}
感谢格林丘
这个帮助类管理GET和POST请求的参数:
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参数我在 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,以便在完成之前取消它。
希望这可以帮助。
这可能会帮助你...
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);
}
对于未来的读者
我喜欢和Volley一起工作。为了节省开发时间,我尝试编写小型方便的库Gloxey Netwok Manager来为我的项目设置 Volley。它包括 JSON 解析器和其他有助于检查网络可用性的其他方法。
使用ConnectionManager.class
哪些不同的方法可用于Volley String和Volley JSON请求。您可以发出带有或不带有标头的GET、PUT、POST、DELETE请求。您可以在此处阅读完整的文档。
只需将此行放在您的 gradle 文件中。
dependencies {
compile 'io.gloxey.gnm:network-manager:1.0.1'
}
方法 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
*/
}
});
方法 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 解析器来解析您的 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();
}
要提供POST
参数,请将您的参数发送给JSONObject
构造JsonObjectRequest
函数。第三个参数接受JSONObject
在请求正文中使用的 a。
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);