Volley源码解析(一)Volley中乱码问题及解决方案

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

}

你可能感兴趣的:(android)