Volley使用技巧—–自定义Request
题外话
最近在和网络请求较劲,也初步接触了下volley,看了各路大神的各种理论分析,现在把自己使用volley的一点小经验拿出来和大家分享,特别是在cookie这个小问题上,由于人笨了,纠结了一段时间.
Volley简介
Google I/O 2013上,Volley发布了。Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮。这是Volley名称的由来: a burst or emission of many things or a large amount at once
适合数据量小的,通信频繁的各种请求,官方已经封装好了各种API,而且还提供了很灵活的自定义请求接口,不仅使用起来方便,可扩展性也很强.
获取Volley的方法有很多,这里直接给出jar的包,方便下载
功能介绍
- JSON,图像等的异步下载;
- 网络请求的排序(scheduling)
- 网络请求的优先级处理
- 缓存
- 多级别取消请求和Activity和生命周期的联动(Activity结束时同时取消所有网络请求)
实战演习
由于API都已经封装好了,使用起来也是非常的简单,只需要如下三个步骤:
//新建网络请求的队列
mQueue = Volley.newRequestQueue(getApplicationContext());
//向队列中加入创建好的请求
mQueue.add(new JsonObjectRequest(Method.GET, url, null,
new Listener() {
@Override
public void onResponse(JSONObject response) {
Log.d(TAG, "response : " + response.toString());
}
}, null));
//启动队列,开始执行请求
mQueue.start();
下面用一个小例子来看看Volley的最简单用法:
首先在AndroidManifest.xml中加入如下的权限,否则不能进行网络访问:
<uses-permission android:name="android.permission.INTERNET" />
接下来就是主要的代码部分:
public class MainActivity extends ActionBarActivity {
//提交请求的按钮
private Button request;
//volley的请求队列
private RequestQueue requestQueue;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
request = (Button) findViewById(R.id.request);
//初始化请求队列
requestQueue = Volley.newRequestQueue(getApplicationContext());
request.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//处理请求成功返回的结果
Response.Listener<String> listener = new Response.Listener<String>() {
@Override
public void onResponse(String s) {
Log.e("dada", s);
}
};
//处理请求错误返回的结果
Response.ErrorListener errorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
Log.e("error", volleyError.toString());
}
};
//实例化请求对象
StringRequest stringRequest = new StringRequest("http://www.baidu.com", listener, errorListener);
//向队列中加入请求
requestQueue.add(stringRequest);
requestQueue.start();
}
});
}
}
上面的属于直接用官方封装好了的request,但是如果官方的request不符合自己的条件,比如说下面这个JSONArrayRequest的代码就是官方给出的:
/**
* A request for retrieving a {@link JSONArray} response body at a given URL.
*/
public class JsonArrayRequest extends JsonRequest<JSONArray> {
/**
* Creates a new request.
* @param url URL to fetch the JSON from
* @param listener Listener to receive the JSON response
* @param errorListener Error listener, or null to ignore errors.
*/
public JsonArrayRequest(String url, Listener<JSONArray> listener, ErrorListener errorListener) {
super(Method.GET, url, null, listener, errorListener);
}
//这个函数是在请求执行完成后,对返回的结果NetworkResponse进行处理,实际上这个结果是Volley已经处理过一次,这里再将这个结果转化为想要的格式类型,在后面的StringRequest中也可以看到相同格式的结果,这对我们自定义request很有帮助
@Override
protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString =
new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONArray(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
}
不难发现上面的JSONArrayRequest只允许进行get请求,而无法进行post请求,于是需要自己去定义.再看看官方给出的StringRequest.java源代码:
/**
* 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);
}
//这个地方和上面的JSONArrayRequest请求的返回结果都相同,都是NetworkResponse,我们在自定义的时候也可以模仿这这些处理进行操作.
@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类继承
- 相应的构造方法,参数可以参照上面的几种,自选
- 处理返回结果paraseNetworkResponse(NetworkResponse response)
下面是自定义的请求代码:
public class JsonArrayRequestPlus extends Request<JSONArray>{
//请求完成之后的回调方法,用来传递请求结果
private final Response.Listener<JSONArray> mListener;
/**
* 构造方法
* @param method(请求方法)
* @param url(请求的url)
* @param listener(请求成功后处理结果的监听器)
* @param errorListener(请求错误后的监听器)
*/
public JsonArrayRequestPlus(int method,
String url,
Response.Listener<JSONArray> listener,
Response.ErrorListener errorListener) {
super(method, url, errorListener);
mListener = listener;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = super.getHeaders();
if(headers == null || headers.equals(Collections.emptyMap())){
headers = new HashMap<>();
}
RequestQueueController.get().addSessionCookie(headers);
return headers;
}
//将结果传递到构造方法中listener实例化的地方
@Override
protected void deliverResponse(JSONArray jsonArray) {
mListener.onResponse(jsonArray);
}
//对NetworkResponse进行处理,处理的方式直接copy的JSONArrayRequest
@Override
protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
RequestQueueController.get().checkSessionCookie(response.headers);
try {
String jsonString =
new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONArray(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
}
自定义的JSONArrayRequestPlus能保证返回的结果为JSONArray的同时,还能满足get和post请求,更多的自定义Request需要联系实际的情况来定.今天的自定义Request就到这里咯,有什么错误或者不懂得给我留言或者直接Q我2319821734,希望和大家能共同的进步~