首页 > 代码库 > 详细解读Volley(四)—— 自定义Request

详细解读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 one rrorResponse(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 one rrorResponse(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 one rrorResponse(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

详细解读Volley(四)—— 自定义Request