通常Volley只会用到两个类RequestQueue 和Request,首先创建一个RequestQueue,RequestQueue管理工作线程并将解析的结果发送给主线程。然后传递一个或者多个Request 对象给他。
Request 的构造函数的参数包含请求类型(GET, POST, 等等)、数据源的url、以及事件监听者。根据请求类型的不同,可能还需要一些其他的参数。
public class MarsWeather extends Application { private RequestQueue mRequestQueue; private static MarsWeather mInstance; @Override public void onCreate() { super.onCreate(); mInstance = this; mRequestQueue = Volley.newRequestQueue(getApplicationContext()); } public static synchronized MarsWeather getInstance() { return mInstance; } public static final String TAG = MarsWeather.class.getName(); public RequestQueue getRequestQueue() { return mRequestQueue; } public <T> void add(Request<T> req) { req.setTag(TAG);// TAG可以是任意值 getRequestQueue().add(req); } public void cancel() { mRequestQueue.cancelAll(TAG); } }
Volley实现了三种常见的请求类型:
String url = "http://httpbin.org/html"; // Request a string response
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { // 请求响应成功
System.out.println(response.substring(0,100)); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // 请求失败
System.out.println("Something went wrong!"); error.printStackTrace(); } }); // Add the request to the queue
Volley.newRequestQueue(this).add(stringRequest);
String url = "http://httpbin.org/get?site=code&network=tutsplus"; JsonObjectRequest jsonRequest = new JsonObjectRequest (Request.Method.GET, url, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { // the response is already constructed as a JSONObject!
try { response = response.getJSONObject("args"); String site = response.getString("site"), network = response.getString("network"); System.out.println("Site: "+site+"\nNetwork: "+network); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { error.printStackTrace(); } }); Volley.newRequestQueue(this).add(jsonRequest);
如果你需要,还可以请求JSONArray ,只需用JsonArrayRequest 替代JsonObjectRequest就可以了。
因为是请求图片,所以没有http类型参数,图片请求总是get的。有三种请求图片的方法。
4.3.1.、ImageRequest。通过提供的Url,她将你请求的图片显示在一个普通的ImageView中。压缩与大小调整的操作都发生在工作线程中。
String url = "http://i.imgur.com/Nwk25LA.jpg"; mImageView = (ImageView) findViewById(R.id.image); ImageRequest imgRequest = new ImageRequest(url, new Response.Listener<Bitmap>() { @Override public void onResponse(Bitmap response) { mImageView.setImageBitmap(response); } }, 0, 0, ImageView.ScaleType.FIT_XY, Bitmap.Config.ARGB_8888, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { mImageView.setBackgroundColor(Color.parseColor("#ff0000")); error.printStackTrace(); } });
Volley.newRequestQueue(this).add(imgRequest);
第一个参数是图片的url,第二个是结果的listener,第三、第四个参数是maxWidth(最大宽度) 和 maxHeight(最大高度),可以设置为0来忽略他们。然后是用于计算图片所需大小的ScaleType,然后是用于指定图片压缩方式的参数,我建议总是使用 Bitmap.Config.ARGB_8888,最后是一个错误listener。
注:Volley默认会将这种请求的优先级设置为low。
@Override public Priority getPriority() { return Priority.LOW; }
4.3.2、ImageLoader类。你可以将之想象成数量庞大的ImageRequests,比如生成一个带有图片的ListView。
// ImageLoader这个类需要一个Request的实例以及一个ImageCache的实例,但是Volley并没有提供默认的实现 RequestQueue mRequestQueue = Volley.newRequestQueue(this); final LruCache<String, Bitmap> mImageCache = new LruCache<String, Bitmap>(20); ImageCache imageCache = new ImageCache() { @Override public void putBitmap(String key, Bitmap value) { mImageCache.put(key, value); } @Override public Bitmap getBitmap(String key) { return mImageCache.get(key); } };
ImageLoader mImageLoader = new ImageLoader(mRequestQueue, imageCache); // imageView是一个ImageView实例 // ImageLoader.getImageListener的第二个参数是默认的图片resource id // 第三个参数是请求失败时候的资源id,可以指定为0 ImageListener listener = ImageLoader.getImageListener(imageView, android.R.drawable.ic_menu_rotate,android.R.drawable.ic_delete); mImageLoader.get(url, listener);// 这个方法会去加载图片
4.3.3、NetworkImageView。
// 继承自ImageView public class NetworkImageView extends ImageView // 添加了一个setImageUrl方法,参数包含一个Url地址和一个ImageLoader对象,ImageLoader可参照上面的 public void setImageUrl(String url, ImageLoader imageLoader) {} // 核心方法 private void loadImageIfNecessary(final boolean isInLayoutPass){ // 内部实现,boolean 类型参数代表是否重新请求网络 ,true:重新请求 false:取缓存 // 内部实现和ImageLoader类似,都是通过ImageContainer中new一个ImageListener,在ImageListener,只是做了Url的空判断,如果Url为null,则调用ImageContainer.cancelRequest();取消请求。 }
网络请求下载图片显示,可以使用此控件,比传统的ImageView多了网络处理,也添加了2个方法,设置开始下载的默认图和下载出错后显示图。
public void setDefaultImageResId(int defaultImage) { mDefaultImageId = defaultImage; } public void setErrorImageResId(int errorImage) { mErrorImageId = errorImage; }
从get请求切换到post请求是非常简单的。你只需要在request的构造方法中改变Request.Method,同时重写getParams方法,返回包含请求参数的Map<String, String>。
String url = "http://httpbin.org/post"; StringRequest postRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() { @Override public void onResponse(String response) { try { JSONObject jsonResponse = new JSONObject(response).getJSONObject("form"); String site = jsonResponse.getString("site"), network = jsonResponse.getString("network"); System.out.println("Site: "+site+"\nNetwork: "+network); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { error.printStackTrace(); } }
) { @Override protected Map<String, String> getParams() { Map<String, String> params = new HashMap<>(); // 这里返回post参数:
params.put("site", "code"); params.put("network", "tutsplus"); return params; } }; Volley.newRequestQueue(this).add(postRequest);
如果你想取消所有的请求,在onStop方法中添加如下代码:
@Override protected void onStop() { super.onStop(); mRequestQueue.cancelAll(new RequestQueue.RequestFilter() { @Override public boolean apply(Request<?> request) { // do I have to cancel this?
return true; // -> always yes
} }); }
还可以根据TAG来取消请求。例如在构造GET请求的时候,设置一个TAG:
request.setTag("GET"); mRequestQueue.add(request);
取消TAG为"GET"的请求
mRequestQueue.cancelAll("GET"); // 假设你已经有了一个RequestQueue变量
默认情况下,Volley将请求的优先级设置为普通。一般这也没什么问题,然而在我们的应用中,两种请求的差别很大,有必要让它们在队列中有不同的优先级。就需要重写一个Request
public class CustomJsonRequest extends JsonObjectRequest { public CustomJsonRequest(int method, String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) { super(method, url, jsonRequest, listener, errorListener); } private Priority mPriority; public void setPriority(Priority priority) { mPriority = priority; } @Override public Priority getPriority() { return mPriority == null ? Priority.NORMAL : mPriority; } }
CustomJsonRequest request = new CustomJsonRequest(Request.Method.GET, RECENT_API_ENDPOINT, null, null, null); // 为了节简代码,方便演示setPriority方法,我将上面的listener全部设为null了
request.setPriority(Request.Priority.HIGH); Volley.newRequestQueue(getApplicationContext());.add(request);
Priority.LOW // images, thumbnails, ... Priority.NORMAL // residual Priority.HIGH // descriptions, lists, ... Priority.IMMEDIATE // login, logout, ...