Volley的简单介绍http://blog.csdn.net/chengshuyuan_uestc/article/details/51755189
Volley源码解析(一)Volley中乱码问题及解决方案http://blog.csdn.net/chengshuyuan_uestc/article/details/51755191
Volley源码分析(二)-Volley中的Request类http://blog.csdn.net/chengshuyuan_uestc/article/details/51755197
Volley源码解析(三)网络请求流程http://blog.csdn.net/chengshuyuan_uestc/article/details/51755201
1 返回值乱码问题
我们在使用Volley进行网络请求非常的简单,如请求一个字符串只需要定义一个StringRequest的对象就可以了。如:
StringRequest stringRequest = new StringRequest("http://www.baidu.com",
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
tv_string.setText(response.toString());
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
tv_string.setText("error");
}
}
);
没有任何问题,可是真的是这样吗?在我们一直放心使用Volley进行网络请求的时候,突然发现请求的字符串乱码了?这时为什么呢?难道有bug?解决这个问题只能从源码入手。
我们看一下StringRequest的源码,StringRequest继承与Requst(其他如JsonRequest, ImageRequest也是一样)。 其中实现了两个在Requst类中定义的抽象函数
- deliverResponse(String response)
- Response parseNetworkResponse(NetworkResponse response)
我们重点关注第二个函数parseNetworkResponse,因为这是解析网络请求返回的Response,解析好之后交给deliverResponse()函数来递交,这一点可以从两个函数的函数名称和参数以及返回值就可以看出来,当然详细的调用过程我们会在下一篇博客中进行分析。
我们看一下parseNetworkResponse(NetworkResponse response)函数的源码:
//StringRequst类中
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
在这个函数中,通过new String(byte[] data, String charsetName)来解析网络的数据,即根据charsetName设定的编码格式解析成String数据,其中编码格式charsetName通过HttpHeaderParser.parseCharset(response.headers)获得。我们查看一下parseCharset(response.headers)函数的实现。
/**
* Returns the charset specified in the Content-Type of this header,
* or the HTTP default (ISO-8859-1) if none can be found.
*/
public static String parseCharset(Map<String, String> headers) {
return parseCharset(headers, HTTP.DEFAULT_CONTENT_CHARSET);
}
看注释,该函数返回http响应报文(Response)中返回的Content-Type参数,如果Response中没有包含这个参数,就使用默认的编码格式,即ISO-8859-1。这下我们明白了,使用的编码格式不对,肯定会乱码啊。
2 乱码问题解决方案
解决这个问题有两个方法:
- 在服务器返回的Response中设定编码格式为UTF-8(但如果我们请求的是他人服务器上的内容,这就没有办法操作)
- 重新定义一个StringRequest类,在解析返回的Response时直接设定编码格式为UTF-8
public class MyStringRequest extends StringRequest {
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
parsed = new String(response.data, "utf-8"));
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
}