前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Volley学习笔记 | 关于源码中Request、Response、Listener泛型的理解(附XMLRequest自定义代码)

Volley学习笔记 | 关于源码中Request、Response、Listener泛型的理解(附XMLRequest自定义代码)

作者头像
凌川江雪
发布2019-07-10 14:40:14
6410
发布2019-07-10 14:40:14
举报
文章被收录于专栏:李蔚蓬的专栏李蔚蓬的专栏
  • 话不多说,理解了这个几个泛型之间的联系, 也就能把Volley框架中自定义Request的步骤过程和原理理解个七七八八;

首先看下StringRequest的源码,如下所示:

代码语言:javascript
复制
/**
 * A canned request for retrieving the response body at a given URL as a String.
 */
public class StringRequest extends Request<String> {
    private final Listener<String> mListener;
 
    /**
     * Creates a new request with the given method.
     *
     * @param method the request {@link Method} to use
     * @param url URL to fetch the string at
     * @param listener Listener to receive the String response
     * @param errorListener Error listener, or null to ignore errors
     */
    public StringRequest(int method, String url, Listener<String> listener,
            ErrorListener errorListener) {
        super(method, url, errorListener);
        mListener = listener;
    }
 
    /**
     * Creates a new GET request.
     *
     * @param url URL to fetch the string at
     * @param listener Listener to receive the String response
     * @param errorListener Error listener, or null to ignore errors
     */
    public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) {
        this(Method.GET, url, listener, errorListener);
    }
 
    @Override
    protected void deliverResponse(String response) {
        mListener.onResponse(response);
    }
 
    @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));
    }
}
  • 类型Request源码中的parseNetworkResponse() 是对Response进行第一步的解析—— 把服务器的响应数据组织成对应类型Request类型Response, 如:
    • StringRequest中的parseNetworkResponse() 把服务器的响应数据组织成String类型, Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); ( Response<String> parseNetworkResponse(NetworkResponse response),String parsed); ImageRequestbitmapResponse.success(bitmap, HttpHeaderParser.parseCacheHeaders(response)); (Response<Bitmap> parseNetworkResponse(NetworkResponse response) ) XMLRequestXmlPullParser Response<XmlPullParser> parseNetworkResponse(NetworkResponse response)
代码语言:javascript
复制
@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));
    }
  • 然后这个Response会传给Response.success()Response.success(xmlPullParser, HttpHeaderParser.parseCacheHeaders(response));
  • 接着会在deliverResponse()中 将这个response传给mListener.onResponse()
代码语言:javascript
复制
    @Override
    protected void deliverResponse(String response) {
        mListener.onResponse(response);
    }
  • 在实例化一个类型Request的时候, 我们传给了构造方法一个重写了onResponse()Listener<对应类型>, 也就是说, 我们在实例化一个类型Request的时候, 在重写的onResponse()中, Response进行了第二次解析—— 即,把首次解析组织好的数据/对象 提现成具体的业务实现;

下面是XMLRequest的自定义代码与使用例程:

  • 使用例程:
代码语言:javascript
复制
        XMLRequest xmlRequest = new XMLRequest(
                "http://flash.weather.com.cn/wmaps/xml/china.xml",
                new Response.Listener<XmlPullParser>() {
                    @Override
                    public void onResponse(XmlPullParser response) {
                        try {
                            int eventType = response.getEventType();
                            while (eventType != XmlPullParser.END_DOCUMENT) {
                                switch (eventType) {
                                    case XmlPullParser.START_TAG:
                                        String nodeName = response.getName();
                                        if ("city".equals(nodeName)) {
                                            String pName = response.getAttributeValue(0);
                                            Log.d("TAG", "pName is " + pName);

                                            reponseContent += pName;
                                            reponseContent += "\n";
                                        }
                                        break;
                                }
                                eventType = response.next();
                            }
                            oriString = new String(reponseContent.getBytes("ISO-8859-1"), "utf-8");
                            responseText.setText(oriString);
                        } catch (XmlPullParserException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("TAG", error.getMessage(), error);
            }
        });
        mQueue.add(xmlRequest);
  • XMLRequest的自定义代码:
代码语言:javascript
复制
public class XMLRequest extends Request<XmlPullParser> {
 
    private final Listener<XmlPullParser> mListener;
 
    public XMLRequest(int method, String url, Listener<XmlPullParser> listener,
            ErrorListener errorListener) {
        super(method, url, errorListener);
        mListener = listener;
    }
 
    public XMLRequest(String url, Listener<XmlPullParser> listener, ErrorListener errorListener) {
        this(Method.GET, url, listener, errorListener);
    }
 
    @Override
    protected Response<XmlPullParser> parseNetworkResponse(NetworkResponse response) {
        try {
            String xmlString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlPullParser xmlPullParser = factory.newPullParser();
            xmlPullParser.setInput(new StringReader(xmlString));
            return Response.success(xmlPullParser, HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (XmlPullParserException e) {
            return Response.error(new ParseError(e));
        }
    }
 
    @Override
    protected void deliverResponse(XmlPullParser response) {
        mListener.onResponse(response);
    }
 
}

附上写demo时候遇到的两个bug,以及相关的解决办法的文章: 网络安全配置问题:

xml解析结果乱码 解决方法: new String(reponseContent.getBytes("ISO-8859-1"), "utf-8"); 相关文章:

  • 如何去改变String的编码格式
  • 关于"ISO-8859-1"
  • 小结一下, 总而言之我们可以看到, public class XMLRequest extends Request<XmlPullParser> Request<XmlPullParser>的泛型, protected Response<XmlPullParser> parseNetworkResponse(NetworkResponse response) Response<XmlPullParser>的泛型, private final Listener<XmlPullParser> mListener; Listener<XmlPullParser>的泛型, 都是一致的, 是因,
    • Request<XmlPullParser>的泛型指定自定义二级Request的类型,
    • Response<XmlPullParser>的泛型表明 parseNetworkResponse()进行第一步解析的返回结果类型, 把服务器的响应数据组织成对应类型Request的类型;
    • Listener<XmlPullParser>的泛型 对应着Listener传递的Response的类型, 也即表明二次解析提现业务时的操作对象(即Response,第一步解析的返回结果类型) 也即onResponse()的参数类型
  • 另外, 自定义Gson的时候,因为类型不明确,所以用T占位, 使用时用对应的类作为参数即可: 如例程: Response.success(mGson.fromJson(jsonString, mClass)mGson.fromJson(jsonString, mClass)mClass(private Class<T> mClass;) 对应gson.fromJson(jsonData, new TypeToken<List<T>>(){}.getType());中的 new TypeToken<List<T>>(){}.getType()
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.07.09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档