在上一节中,讲解了Volley基本的应用,但是还有一些小问题,这里接着讲解。
Volley 所有的操作几乎都是围绕RequestQueue来进行的;里面维护了网络请求,请求队列、缓存队列等东西,如果每个请求都创建一个RequestQueue对性能会有很多影响的,甚至会导致OutOfMemery;所以整个应用采取一个RequestQueue,将它做成单例的。因为在创建RequestQueue的时候会用到Context,最好使用应用级的上下文getApplicationContext();这样应用至始至终都用到一个上文和一个请求队列。个人习惯在Application做这些操作,当然如果不想这样做,也可以单独写一个单例类。
不要忘记在AndroidMenifext.xml的中
application
节点下设置name
属性
代码如下:
public class App extends Application {
private static RequestQueue mQueue;
@Override
public void onCreate() {
super.onCreate();
mQueue = Volley.newRequestQueue(getApplicationContext());
}
public static RequestQueue getQueue() {
return mQueue;
}
}
在需要使用RequestQueue的时候可以像这样使用:
RequestQueue queue = App.getQueue();
Volley 支持 GET、POST、PUT、DELETE、HEAD、OPTIONS、TRACE、PATCH 7种请求,这里只介绍常用的GET和POST。
在上一节中的StringRequest的请求方式就是典型的GET请求,在Volley的Request类里,有一个接口定义了支持的上面的7种请求方法。
/**
* Supported request methods.
*/
public interface Method {
int DEPRECATED_GET_OR_POST = -1;
int GET = 0;
int POST = 1;
int PUT = 2;
int DELETE = 3;
int HEAD = 4;
int OPTIONS = 5;
int TRACE = 6;
int PATCH = 7;
}
GET 请求的参数都是写在URL里面,所以要简单一些,只要组拼URL 就行了。
private void requestByVolley() {
//1.组拼URL
String mUrlStr = "http://apis.juhe.cn/mobile/get?key=" + APP_KEY + "&phone=";
mUrlStr = mUrlStr + "135******";
//2.获取一个RequestQueue
RequestQueue queue = App.getQueue();
//3.创建一个请求,其返回的结果以String 形式返回
StringRequest request = new StringRequest(Request.Method.GET, mUrlStr, new Response.Listener<String>() {
@Override
public void onResponse(String response) {//请求成功返回的回调
//将返回的数据显示到TextView上
mTextView.setText(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {//请求失败返回的回调
mTextView.setText(error.getMessage());
}
});
//4.将请求添加的请求队列中,在这里请求就已经开始了
queue.add(request);
}
这个就是简单以String为返回形式的请求。类似有还有JsonObjectRequest、JsonArrayRequest、ImageRequest,下面会一一举例。
在返回的回调方法里,它是返回的结果是以JSONObject 返回的。
private void requestByVolley() throws JSONException {
//1.组拼URL
String phone = "135*******";
String mUrlStr = "http://apis.juhe.cn/mobile/get?key=" + APP_KEY + "&phone=" + phone;
//2.获取一个RequestQueue
RequestQueue queue = App.getQueue();
//3.创建一个请求,其返回的结果以 JSONObject 形式返回,第三个JSONObject参数表示在URL里是否包含JSON形式的内容,如果有可以添加,没有就可以填null
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, mUrlStr, null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) { //请求成功返回的回调
VolleyLog.d(response.toString()); //使用Volley带有的Log工具类打印一下结果
}
},在返回的回调方法里,它是返回的结果是以JSONObject 返回的。
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) { //请求失败返回的回调
VolleyLog.e(error.toString());
}
});
//4.将请求添加的请求队列中,在这里请求就已经开始了
queue.add(request);
}
在返回的回调方法里,它是返回的结果是以JSONArray 返回的。暂时没有找到返回的结果以JSONArray返回的接口,但是例子是有效。
private void requestByVolley() throws JSONException {
//1.组拼URL
String mUrlStr = "http://apis.******";
//2.获取一个RequestQueue
RequestQueue queue = App.getQueue();
//3.创建一个请求,其返回的结果以 JSONArray 形式返回,第三个JSONObject参数表示在URL里是否包含JSON形式的内容,如果有可以添加,没有就可以填null
JsonArrayRequest request = new JsonArrayRequest(Request.Method.GET, mUrlStr, null,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) { //请求成功返回的回调
VolleyLog.d(response.toString()); //使用Volley带有的Log工具类打印一下结果
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) { //请求失败返回的回调
VolleyLog.e(error.toString());
}
});
//4.将请求添加的请求队列中,在这里请求就已经开始了
queue.add(request);
}
POST 请求跟GET 请求类似,只是添加了一些请求参数,下面看例子
在StringRequest参数里面没有提供提交 POST 请求设置参数的方法,所以只能在StringRequest的匿名类中重写getParams()方法来设置请求参数;就像下面的例子:
StringRequest stringRequest = new StringRequest(Method.POST, url, listener, errorListener) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> map = new HashMap<String, String>();
map.put("parame1", "value1");
map.put("parame1", "value2");
return map;
}
};
具体请求的代码如下,使用的是聚合数据中 搜索新闻的接口
private void requestByVolley(){
//1.组拼URL
String mUrlStr = "http://op.juhe.cn/onebox/news/query";
//2.获取一个RequestQueue
RequestQueue queue = App.getQueue();
//3.创建一个请求,其返回的结果以String 形式返回
StringRequest stringRequest = new StringRequest(Request.Method.POST, mUrlStr, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
mTextView.setText(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mTextView.setText(error.getMessage());
}
}){
//在StringRequest参数里面没有提供提交 POST 请求设置参数的方法,所以只能重写父类Request的getParams()方法来设置请求参数
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> parames = new HashMap<>();
parames.put("q","普京");//搜索关于普京的新闻
parames.put("key",APP_KEY);
return parames;
}
};
//4.将请求添加的请求队列中,在这里请求就已经开始了
queue.add(stringRequest);
}
就像添加请求参数一样,可以重写getHeaders()
方法,比如我们需要在header里面设置 apikey
和Content-Type
private void requestByVolley(){
//1.组拼URL
String mUrlStr = "http://op.juhe.cn/onebox/news/query";
//2.获取一个RequestQueue
RequestQueue queue = App.getQueue();
//3.创建一个请求,其返回的结果以String 形式返回
StringRequest stringRequest = new StringRequest(Request.Method.POST, mUrlStr, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
mTextView.setText(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mTextView.setText(error.getMessage());
}
}){
//设置请求的Header
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
headers.put("apiKey", "xxxxxxxxxxxxxxx");
return headers;
}
};
//4.将请求添加的请求队列中,在这里请求就已经开始了
queue.add(stringRequest);
}
ImageRequest 是为了请求图片设计的
private void requestByVolley() throws JSONException {
//1.组拼URL
String mUrlStr = "http://cdn.duitang.com/uploads/item/201508/29/20150829042518_2fRiH.jpeg";
//2.获取一个RequestQueue
RequestQueue queue = App.getQueue();
//3.创建一个请求,其返回的结果以 Bitmap 形式返回,第三个参数是给POST请求预备的,GET请求可以写null
ImageRequest stringRequest = new ImageRequest(mUrlStr, new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap response) {
mImageView.setImageBitmap(response);
}
}, 0, 0, ImageView.ScaleType.CENTER, Bitmap.Config.RGB_565, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e(error.getMessage());
//当请求失败时,设置默认显示图
mImageView.setImageResource(R.drawable.default_icon);
}
});
//4.将请求添加的请求队列中,在这里请求就已经开始了
queue.add(stringRequest);
}
ImageRequest 稍微跟其他的Request不一样的是,参数比较多。第一个参数是图片的URL,第二个参数是请求成功的回调;第三第四个参数分别用于指定允许图片最大的宽度和高度;第五参数是ImageView的
ScaleType
参数,这参数相当于ImageView在布局里的android:scaleType
;第六个参数是图片的颜色属性;第七个参数是图片请求失败的回调。关于第三个跟第四个参数,如果指定的网络图片的宽度或高度大于这里的最大值,则会对图片进行压缩,指定成0的话就表示不管图片有多大,都不会进行压缩。
关于第六个参数,在
Bitmap.Config
都有定义;图片的颜色属性,一般有ALPHA_8
,RGB_565
,ARGB_4444
,ARGB_8888
,常用的是RGB_565
和ARGB_8888
,其中ARGB_8888
可以展示最好的颜色属性,每个图片像素占据4个字节的大小,而RGB_565
则表示每个图片像素占据2个字节大小。
在Volley里直接使用JsonObjectRequest
和JsonArrayRequest
实现POST请求是不行的,因为这两个类继承了JsonRequest
这个抽象类,它重写了父类Request
的getBody()
方法;它将构造函数中的第二个参数直接encoding,然后作为post参数提交了;所以需要自己实现定义的Request。关于自定义Request的内容我们留到下一节介绍;下一节我们还会介绍ImageLoader的内容。