PS:看了9年的小说,自己开始动手写了一本,请各位猿们动动手指,点击下,有起点账号的可以收藏下!!《武意长存》
volley是Google 在2013年的Google I/O大会上推出了一个网络通信框架,它不仅仅是一个网络异步加载库,也是一个图片加载库。
这里主要是简单的介绍下其异步访问网络的使用。
这里再次贴上服务端代码(之前有关网络访问的第一篇文章已有)
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String username = request.getParameter("username");
String password = request.getParameter("password");
username = new String(username.getBytes("iso8859-1"), "utf-8");
if("张三".equals(username) && "123".equals(password)){
out.println("登录成功!");
}else {
out.println("登录失败!");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
客户端界面:
点击loginByVolleyGet按钮,调用以下方法
public void loginByVolleyGet(View view){
final String username = etUsername.getText().toString().trim();
final String password = etPassword.getText().toString().trim();
if(TextUtils.isEmpty(username) || TextUtils.isEmpty(password)){
Toast.makeText(this, "用户名或密码不能为空!", Toast.LENGTH_SHORT).show();
}else {
String path = null;
try {
path = "http://110.82.97.224:8080/server/LoginServlet?username="+URLEncoder.encode(username, "utf-8")+"&password="+URLEncoder.encode(password, "utf-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
//首先需要获取到一个RequestQueue对象
RequestQueue mQueue = Volley.newRequestQueue(this);
//第一个参数是请求方式,第二个参数就是目标服务器的URL地址,第三个参数是服务器响应成功的回调,第四个参数是服务器响应失败的回调
StringRequest stringRequest = new StringRequest(Method.GET, path, new Listener<String>() {
@Override
public void onResponse(String response) {
Toast.makeText(MainActivity.this, "请求成功:"+response, Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "请求失败:"+error, Toast.LENGTH_SHORT).show();
}
});
mQueue.add(stringRequest);
}
}
输入正确的用户名和密码
点击loginByVolleyPost按钮,调用以下方法
public void loginByVolleyPost(View view){
final String username = etUsername.getText().toString().trim();
final String password = etPassword.getText().toString().trim();
if(TextUtils.isEmpty(username) || TextUtils.isEmpty(password)){
Toast.makeText(this, "用户名或密码不能为空!", Toast.LENGTH_SHORT).show();
}else {
String path = "http://110.82.97.224:8080/server/LoginServlet";
//首先需要获取到一个RequestQueue对象
RequestQueue mQueue = Volley.newRequestQueue(this);
//第一个参数是请求方式,第二个参数就是目标服务器的URL地址,第三个参数是服务器响应成功的回调,第四个参数是服务器响应失败的回调
StringRequest stringRequest = new StringRequest(Method.POST, path, new Listener<String>() {
@Override
public void onResponse(String response) {
Toast.makeText(MainActivity.this, "请求成功:"+response, Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "请求失败:"+error, Toast.LENGTH_SHORT).show();
}
}){
@Override
protected Map<String, String> getParams()
throws AuthFailureError {
Map<String, String> map = new HashMap<String, String>();
map.put("username", username);
map.put("password", password);
return map;
}
@Override
protected String getParamsEncoding() {
return super.getParamsEncoding();
}
};
mQueue.add(stringRequest);
}
}
输入正确的账号和密码,此时得到的结果却是 登录失败
<p>看到这里,我起初也很惊讶,以为是不是还要设置参数的编码,不过一看源代码发现参数的默认编码就是UTF-8,。这时我更惊讶了,明明和AsyncHttpClient一样,参数的默认编码都是utf-8, 为啥同样的服务端代码AsyncHttpClient可以决绝乱码问题,而volley却出错,我这时想到的是可能两者的实现不同,就分别看了下两者的实现方式。</p><p>AsyncHttpClient对于参数编码的设置
</p><pre name="code" class="java">protected String contentEncoding = HTTP.UTF_8;
private HttpEntity createFormEntity() {
try {
return new UrlEncodedFormEntity(getParamsList(), contentEncoding);
} catch (UnsupportedEncodingException e) {
Log.e(LOG_TAG, "createFormEntity failed", e);
return null; // Can happen, if the 'contentEncoding' won't be HTTP.UTF_8
}
}
而 volley 的实现方式却是
<span style="font-size: 12pt; font-family: 宋体;"></span><pre name="code" class="java">/**
* Default encoding for POST or PUT parameters. See {@link #getParamsEncoding()}.
*/
private static final String DEFAULT_PARAMS_ENCODING = "UTF-8";
protected String getParamsEncoding() {
return DEFAULT_PARAMS_ENCODING;
}
public String getBodyContentType() {
return "application/x-www-form-urlencoded; charset=" + getParamsEncoding();
}
/**
* Returns the raw POST or PUT body to be sent.
*
* @throws AuthFailureError in the event of auth failure
*/
public byte[] getBody() throws AuthFailureError {
Map<String, String> params = getParams();
if (params != null && params.size() > 0) {
return encodeParameters(params, getParamsEncoding());
}
return null;
}
/**
* Converts <code>params</code> into an application/x-www-form-urlencoded encoded string.
*/
private byte[] encodeParameters(Map<String, String> params, String paramsEncoding) {
StringBuilder encodedParams = new StringBuilder();
try {
for (Map.Entry<String, String> entry : params.entrySet()) {
encodedParams.append(URLEncoder.encode(entry.getKey(), paramsEncoding));
encodedParams.append('=');
encodedParams.append(URLEncoder.encode(entry.getValue(), paramsEncoding));
encodedParams.append('&');
}
return encodedParams.toString().getBytes(paramsEncoding);
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee);
}
}
从volley的源码我们不难看出,它已经在Http的头部信息指定其参数的字符编码为utf-8,所以服务端也就知道了如何进行解码,因此我们不必再在服务端手动解码,服务端代码只需做如下修改
把下面这行代码删除掉就ok了
username = new String(username.getBytes("iso8859-1"), "utf-8");