zoukankan      html  css  js  c++  java
  • 详细解读Volley(四)—— 自定义Request

    Volley中提供了几个Request,如果我们有特殊的需求,完全可以自定义Request的,自定义Request自然要继承Request,那么本篇就教大家来一步一步地定义一个自己的Request类。

    一、继承Request

    如果我们的request的对象不是string,也不是JsonObject,而是一个奇怪的对象呢?我这里建立了一个类,叫做:Kale,然后定义了一个CustomReqeust去继承Reqeust,得到如下的代码。

    package com.kale.volleytest;
    
    import com.android.volley.NetworkResponse;
    import com.android.volley.Request;
    import com.android.volley.Response;
    import com.android.volley.Response.ErrorListener;
    import com.android.volley.Response.Listener;
    
    public class CustomReqeust extends Request<Kale>{
        
        public CustomReqeust(int method, String url, ErrorListener listener) {
            super(method, url, listener);
        }
    
        @Override
        protected Response<Kale> parseNetworkResponse(NetworkResponse response) {
            // TODO 自动生成的方法存根
            return null;
        }
    
        @Override
        protected void deliverResponse(Kale response) {
            // TODO 自动生成的方法存根
            
        }
    
    }

    分析:

    public CustomReqeust(int method, String url, ErrorListener listener)

    构造函数中调用了父类的方法,初始化了当前对象。传入三个参数:①请求方式,即POST/GET,②请求的URL,③出错时的回调监听器

    protected Response<Kale> parseNetworkResponse(NetworkResponse response)

    解析网络响应的结果,从NetworkResponse的代码中我们就可以知道它里面有什么东西了。

    /**
     * Data and headers returned from {@link Network#performRequest(Request)}.
     */
    public class NetworkResponse {
        /**
         * Creates a new network response.
         * @param statusCode the HTTP status code
         * @param data Response body
         * @param headers Headers returned with this response, or null for none
         * @param notModified True if the server returned a 304 and the data was already in cache
         * @param networkTimeMs Round-trip network time to receive network response
         */
        public NetworkResponse(int statusCode, byte[] data, Map<String, String> headers,
                boolean notModified, long networkTimeMs)

    响应码啊,请求头什么的,最最主要的就是这个比特数组的data,响应的结果就在里面。我们可以自由的进行处理了~

    protected void deliverResponse(Kale response)

    分发响应的结果,我们可以通过将这个response放到监听器里来获取响应结果。

    二、分析StringRequest

    我们现在已经对request的子类有了基本的认识,现在就来看看StringRequest的源码吧,别担心,很短!

    package com.android.volley.toolbox;public class StringRequest extends Request<String> {
        // 建立监听器来获得响应成功时返回的结果
        private final Listener<String> mListener; 
    
    
        // 传入请求方法,url,成功时的监听器,失败时的监听器
        public StringRequest(int method, String url, Listener<String> listener,
                ErrorListener errorListener) {
            super(method, url, errorListener);
            // 初始化成功时的监听器
            mListener = listener;
        }
    
        /**
         * Creates a new GET request.
         * 建立一个默认的GET请求,调用了上面的构造函数
         */
        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 {
                // 调用了new String(byte[] data, String charsetName) 这个构造函数来构建String对象,
                // 将byte数组按照特定的编码方式转换为String对象
                // 主要部分是data
                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了,其实没啥高深的东西。

    三、自定义XMLRequest

    代码来自:http://blog.csdn.net/guolin_blog/article/details/17612763

    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);  
        }  
      
    } 

    这里用到了XmlPull的知识,如果不是很了解,可以去这篇文章看看:http://www.cnblogs.com/tianzhijiexian/p/4020250.html

    测试代码:

    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);  
                                        }  
                                        break;  
                                    }  
                                    eventType = response.next();  
                                }  
                            } 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);

    结果:

    四、自定义GsonRequest

    代码来自:http://blog.csdn.net/guolin_blog/article/details/17612763

    public class GsonRequest<T> extends Request<T> {
    
        private final Listener<T> mListener;
    
        private Gson mGson;
    
        private Class<T> mClass;
    
        public GsonRequest(int method, String url, Class<T> clazz, Listener<T> listener,
                ErrorListener errorListener) {
            super(method, url, errorListener);
            mGson = new Gson();
            mClass = clazz;
            mListener = listener;
        }
    
        public GsonRequest(String url, Class<T> clazz, Listener<T> listener,
                ErrorListener errorListener) {
            this(Method.GET, url, clazz, listener, errorListener);
        }
    
        @Override
        protected Response<T> parseNetworkResponse(NetworkResponse response) {
            try {
                String jsonString = new String(response.data,
                        HttpHeaderParser.parseCharset(response.headers));
                return Response.success(mGson.fromJson(jsonString, mClass),
                        HttpHeaderParser.parseCacheHeaders(response));
            } catch (UnsupportedEncodingException e) {
                return Response.error(new ParseError(e));
            }
        }
    
        @Override
        protected void deliverResponse(T response) {
            mListener.onResponse(response);
        }
    
    }

    代码十分简单,先是将服务器响应的数据解析出来,然后通过调用Gson的fromJson方法将数据组装成对象。在deliverResponse方法中仍然是将最终的数据进行回调。

    用法:

    建立一个对象类,比如这里的weather、WeatherInfo类,然后初始化GsonRequest对象,最后把GsonRequest对象添加到队列中。

    Weather:

    public class Weather {
    
        private WeatherInfo weatherinfo;
    
        public WeatherInfo getWeatherinfo() {
            return weatherinfo;
        }
    
        public void setWeatherinfo(WeatherInfo weatherinfo) {
            this.weatherinfo = weatherinfo;
        }
    
    }
    View Code

    WeatherInfo:

    public class WeatherInfo {
    
        private String city;
    
        private String temp;
    
        private String time;
    
        public String getCity() {
            return city;
        }
    
        public void setCity(String city) {
            this.city = city;
        }
    
        public String getTemp() {
            return temp;
        }
    
        public void setTemp(String temp) {
            this.temp = temp;
        }
    
        public String getTime() {
            return time;
        }
    
        public void setTime(String time) {
            this.time = time;
        }
    
    }
    View Code

    Java测试代码:

    GsonRequest<Weather> gsonRequest = new GsonRequest<Weather>(  
            "http://www.weather.com.cn/data/sk/101010100.html", Weather.class,  
            new Response.Listener<Weather>() {  
                @Override  
                public void onResponse(Weather weather) {  
                    WeatherInfo weatherInfo = weather.getWeatherinfo();  
                    Log.d("TAG", "city is " + weatherInfo.getCity());  
                    Log.d("TAG", "temp is " + weatherInfo.getTemp());  
                    Log.d("TAG", "time is " + weatherInfo.getTime());  
                }  
            }, new Response.ErrorListener() {  
                @Override  
                public void onErrorResponse(VolleyError error) {  
                    Log.e("TAG", error.getMessage(), error);  
                }  
            });  
    mQueue.add(gsonRequest); 

    五、重写getBody()方法来添加post参数

    我们可以在JsonRequest类中发现如下代码:

    /** 
      * Returns the raw POST or PUT body to be sent. 
      * 
      * @throws AuthFailureError in the event of auth failure 
      */  
     @Override  
     public byte[] getBody() {  
         try {  
             return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET);  
         } catch (UnsupportedEncodingException uee) {  
             VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",  
                     mRequestBody, PROTOCOL_CHARSET);  
             return null;  
         }  
     }  

    不用看代码,直接看注释,说明这里执行post请求,所以我们可以在这里设置post参数。这里

    return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET); 

    返回的就是post参数了。

    如果我们想要传递POST数据,可以参考上面的代码,重写Request的getBody()方法,放入自己的参数,举例如下:

       /** http请求编码方式 */  
        private static final String PROTOCOL_CHARSET = "utf-8";  
      
        private String mUserName; 
    @Override  
        public byte[] getBody() {  
            try {  
                return mUserName == null ? null : mUserName.getBytes(PROTOCOL_CHARSET);  
            } catch (UnsupportedEncodingException uee) {  
                VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", mUserName, PROTOCOL_CHARSET);  
                return null;  
            }  
        }  

    完整代码(来自:http://blog.csdn.net/ttdevs/article/details/17586205):

    public class CustomReqeust extends Request<String> {  
        /** http请求编码方式 */  
        private static final String PROTOCOL_CHARSET = "utf-8";  
      
        private Listener<String> mListener;  
        private String mUserName;  
      
        public CustomReqeust(String url, String userName, Listener<String> listener, ErrorListener errorListener) {  
            super(Method.POST, url, errorListener);  
            mUserName = userName;  
            mListener = listener;  
        }  
      
        @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));  
        }  
      
        @Override  
        protected void deliverResponse(String response) {  
            mListener.onResponse(response);  
        }  
      
        @Override  
        public byte[] getBody() {  
            try {  
                return mUserName == null ? null : mUserName.getBytes(PROTOCOL_CHARSET);  
            } catch (UnsupportedEncodingException uee) {  
                VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", mUserName, PROTOCOL_CHARSET);  
                return null;  
            }  
        }  
    }  
    View Code

    测试代码:

    private void customRequest() {  
        CustomReqeust request = new CustomReqeust(URL, "CustomVolley", new Listener<String>() {  
      
            @Override  
            public void onResponse(String arg0) {  
                Toast.makeText(getApplicationContext(), arg0, Toast.LENGTH_LONG).show();  
                Log.d("onResponse", arg0);  
            }  
        }, new ErrorListener() {  
      
            @Override  
            public void onErrorResponse(VolleyError arg0) {  
                Toast.makeText(getApplicationContext(), arg0.toString(), Toast.LENGTH_LONG).show();  
                Log.d("onErrorResponse", arg0.toString());  
            }  
        });  
        mQueue.add(request);  
    }  

    抓包结果:

    得到了传递的username = CustomVolley

    参考自:

    http://blog.csdn.net/t12x3456/article/details/9221611

    http://blog.csdn.net/guolin_blog/article/details/17612763

    http://blog.csdn.net/ttdevs/article/details/17586205

  • 相关阅读:
    XSS
    XSS练习小游戏
    CTF中常见的编码
    BugkuCTF
    A、B、C、D和E类IP地址
    JDK和JRE的区别及配置
    SQL注入漏洞测试(HTTP头注入)
    MS17-010远程溢出漏洞(CVE-2017-0143)拿权限
    SQL注入——布尔型盲注注入攻击——手工注入篇——SQL手工注入漏洞测试(MySQL数据库)
    mysql增删改查
  • 原文地址:https://www.cnblogs.com/tianzhijiexian/p/4263139.html
Copyright © 2011-2022 走看看