Android Volley 之自定义Request
转载标明出处:http://blog.csdn.net/lmj623565791/article/details/24589837
今天群里一哥们需要自定义Volley的Request的例子,于是产生了这篇博客。关于Volley的介绍就不多说了,网上例子特别多。
Volley的所有的请求的超类型是Resuest,类结构如下图,所有我们常用的请求都是这个类的子类,那么我们自定义View肯定也是基于这个类的。
一些简单的用法实例:
RequestQueue newRequestQueue = Volley.newRequestQueue(MainActivity.this); StringRequest stringRequest = new StringRequest("http://www.baidu.com", new Response.Listener<String>() { @Override public void onResponse(String response) { Log.e("TAG", response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("TAG", error.getMessage(), error); } }); JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("http://m.weather.com.cn/data/101010100.html", null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { Log.e("TAG", response.toString()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("TAG", error.getMessage(), error); } }); ImageRequest imageRequest = new ImageRequest("http://imgt6.bdstatic.com/it/u=2,887966933&fm=19&gp=0.jpg", new Response.Listener<Bitmap>() { @Override public void onResponse(Bitmap response) { mImageView.setImageBitmap(response); } }, 0, 0, Config.RGB_565, null); newRequestQueue.add(stringRequest); newRequestQueue.add(imageRequest); newRequestQueue.add(jsonObjectRequest);
基本都是new一个请求,加入请求队列就行了。
好了,下面进入正题,如何自定义自己的Request,其实很简单,咱们打开StringRequest的源码:
public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); mListener = listener; }
构造方法中指明访问的url,method,和回调的接口,毕竟我们要处理数据么。
@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)); }
最终给我们返回的数据就是parsed,比如我们返回的是json字符串,我们就可以在这添几行代码,把字符串转换成对象返回。(很重要的是,返回类型是咱们声明Request的时候定的,是个泛型)。
下面直接上例子:
例子是,通过客户端访问服务器,服务器对客户端进行身份校验后,返回JSON字符串,客户端直接拿到对象。
1、对象:
package com.zhy.velloydemo; public class User { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User [name=" + name + ", age=" + age + "]"; } }
2、自定义的Request
package com.zhy.velloydemo; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map; import com.android.volley.AuthFailureError; import com.android.volley.NetworkResponse; import com.android.volley.ParseError; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.Response.ErrorListener; import com.android.volley.Response.Listener; import com.android.volley.toolbox.HttpHeaderParser; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; public class JsonRequestWithAuth<T> extends Request<T> { private final Gson gson = new Gson(); private final Class<T> clazz; private final Listener<T> listener; private static Map<String, String> mHeader = new HashMap<String, String>(); /** * 设置访问自己服务器时必须传递的参数,密钥等 */ static { mHeader.put("APP-Key", "LBS-AAA"); mHeader.put("APP-Secret", "ad12msa234das232in"); } /** * @param url * @param clazz * 我们最终的转化类型 * @param headers * 请求附带的头信息 * @param listener * @param appendHeader * 附加头数据 * @param errorListener */ public JsonRequestWithAuth(String url, Class<T> clazz, Listener<T> listener, Map<String, String> appendHeader, ErrorListener errorListener) { super(Method.GET, url, errorListener); this.clazz = clazz; this.listener = listener; mHeader.putAll(appendHeader); } @Override public Map<String, String> getHeaders() throws AuthFailureError { // 默认返回 return Collections.emptyMap(); return mHeader; } @Override protected void deliverResponse(T response) { listener.onResponse(response); } @Override protected Response<T> parseNetworkResponse(NetworkResponse response) { try { /** * 得到返回的数据 */ String jsonStr = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); /** * 转化成对象 */ return Response.success(gson.fromJson(jsonStr, clazz), HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (JsonSyntaxException e) { return Response.error(new ParseError(e)); } } }
这里说一下,我在Header中放置了APP-key等数据,也就是说只要我们这个请求发的都会有这几个值,大家开发app时肯定有很多请求参数是需要每次都发往服务器校验的,可以在这里设置。
3、服务器代码:
package com.zhy.servelt; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); String appKey = request.getHeader("APP-Key"); String appSecret = request.getHeader("APP-Secret"); String username = request.getHeader("username"); String password = request.getHeader("password"); if ("admin".equals(username) && "123".equals(password)) { response.setContentType("text/plain;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("{\"name\":\"鸿洋\",\"age\":32}"); out.flush(); } } }
4、测试代码:
Map<String, String> appendHeader = new HashMap<String, String>(); appendHeader.put("username", "admin"); appendHeader.put("password", "123"); String url = "http://172.27.35.1:8080/webTest/TestServlet"; JsonRequestWithAuth<User> userRequest = new JsonRequestWithAuth<User>(url, User.class, new Listener<User>() { @Override public void onResponse(User response) { Log.e("TAG", response.toString()); } }, appendHeader, null); newRequestQueue.add(userRequest);
可以看到我们使用自定义请求实现了我们上述的需求,这里还要说一下,这个例子有两个目的:
1、自定义Request其实很简单,如果不需要Header直接不用复写getHeader那个方法。
2、我们可以利用Header传递一些固定的参数,这比对安全比较高的系统,每次拼一堆xml去服务器,代码能简洁很多,当然了,注意信息安全。
最后补充一下:
哥们问这句什么意思:HttpHeaderParser.parseCharset(response.headers)其实就是获取我们的返回流的编码,也就是我上面服务器设置的utf-8
对于请求的Header和响应Header理解,随便打开个网站,使用浏览器的工具查看一下,每个请求都会包含这两个Header数据。
好了,就到这里~各位留个言、赞一个算对我们的支持~