手撕 Volley (一)
来自 <https://www.jianshu.com/p/33be82da8f25>
Android Volley完全解析(一),初识Volley的基本用法
来自 <https://blog.youkuaiyun.com/guolin_blog/article/details/17482095>
数据量不大,但网络通信频繁的,因此非常适合使用Volley。
- JSON,图像等的异步下载;
- 网络请求的排序(scheduling)
- 网络请求的优先级处理
- 缓存
- 多级别取消请求
- 和Activity和生命周期的联动(Activity结束时同时取消所有网络请求)
一、使用Volley发出请求步骤:
1.、创建RequestQueue对象
RequestQueue mQueue =Volley.newRequestQueue(context);
RequestQueue是一个请求队列对象,
缓存所有的HTTP请求,
RequestQueue内部按照一定的算法并发地发出这些请求,非常合适高并发的,
在每一个需要和网络交互的Activity中创建一个RequestQueue对象就足够了。
2、创建请求对象StringRequest
StringRequeststringRequest = new StringRequest(Method.POST, url, listener, errorListener);
StringRequeststringRequest = new StringRequest(url, listener, errorListener);
第一个参数就是目标服务器的URL地址,
第二个参数是服务器响应成功的回调,
第三个参数是服务器响应失败的回调。
StringRequest stringRequest = new StringRequest(
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d("TAG", response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("TAG", error.getMessage(), error);
}
});
3、将请求加入队列:
mQueue.add(stringRequest);
4、使用StringRequest发出Post请求
1.构造函数中传入Method.POST
2.重写"getParams"方法设置post参数
StringRequest中并没有提供设置POST参数的方法,但是当发出POST请求的时候,Volley会尝试调用StringRequest的父类——Request中的getParams()方法来获取POST参数,那么解决方法自然也就有了,我们只需要在StringRequest的匿名类中重写getParams()方法,在这里设置POST参数就可以了,代码如下所示:
- StringRequest stringRequest = new StringRequest(Method.POST, url, listener, errorListener) {
- @Override
- protected Map<String, String> getParams() throws AuthFailureError { //Volley判断Post方法会调用
- Map<String, String> map = new HashMap<String, String>();
- map.put("params1", "value1");
- map.put("params2", "value2");
- return map;
- }
- };
二、JsonRequest的用法
JsonRequest有两个直接的子类,JsonObjectRequest和JsonArrayRequest
- Map<String, String> map = new HashMap<String, String>();
- map.put("user", "jt1024");
- map.put("psw", "111111");
- JSONObject object = new JSONObject(map);
- JsonObjectRequest request = new JsonObjectRequest(Method.POST, urlpost, object, new Listener<JSONObject>() {
- @Override
- public void onResponse(JSONObject response) {
- tv_resp1.setText(response.toString());
- }
- }, new Response.ErrorListener() {
- @Override
- public void onErrorResponse(VolleyError error) {
- tv_resp1.setText(error.toString());
- }
- });
- request.setTag("volley_JsonObjectRequestPost");
- MyApplication.getInstance().addToRequestQueue(request);
三、图片请求
ImageRequest
- * 第三第四个参数分别用于指定允许图片最大的宽度和高度,如果指定的网络图片的宽度或高度大于这里的最大值,则会对图片进行压缩,
- * 指定成0的话就表示不管图片有多大,都不会进行压缩。
- *
- * @param url
- * 图片地址
- * @param listener
- * @param maxWidth
- * 指定允许图片最大的宽度
- * @param maxHeight
- * 指定允许图片最大的高度 ,如果实际图片比这个大,则自动进行图片压缩
- * @param decodeConfig
- * 指定图片的颜色属性,Bitmap.Config下的几个常量.
- * @param errorListener
- ImageRequest imReq = new ImageRequest(url, new Listener<Bitmap>() {
- @Override
- public void onResponse(Bitmap arg0) {
- iv.setImageBitmap(arg0);
- }
- }, 60, 60, Bitmap.Config.ARGB_8888, new StrErrListener());
- requestQueue.add(imReq);
ImageLoader使用
内部也是使用ImageRequest来实现的,不仅可以帮我们对图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求
- // getImageListener(imageView控件对象,默认图片地址,失败图片地址);
- ImageListener listener = ImageLoader.getImageListener(
imageView,
android.R.drawable.ic_menu_rotate,
android.R.drawable.ic_delete);
- // get(图片地址,listener,宽,高);自动帮你处理图片的宽高再也不怕大图片的oom了 (创建ImageLoader时候带上ImageCach!!!避免OOM)
- ImageLoader imageLoader = new ImageLoader(mQueue, new ImageCache {
- private LruCache<String, Bitmap> mCache;
- public BitmapCache() {
- final int maxSize = (int) (Runtime.getRuntime().maxMemory() / 1024) / 8;
- mCache = new LruCache<String, Bitmap>(maxSize) {
- @Override
- protected int sizeOf(String key, Bitmap bitmap) {
- return bitmap.getRowBytes() * bitmap.getHeight();
- }
- };
- }
- @Override
- public Bitmap getBitmap(String url) {
- return mCache.get(url);
- }
- @Override
- public void putBitmap(String url, Bitmap bitmap) {
- mCache.put(url, bitmap);
- }
- );
mImageLoader.get(url, listener,100,200);
★使用LruCache进行图片缓存
- BitmapCache extends LruCache<String, Bitmap> implements ImageCache {
- // LruCache 原理:Cache保存一个强引用来限制内容数量,每当Item被访问的时候,此Item就会移动到队列的头部。 当cache已满的时候加入新的item时,在队列尾部的item会被回收。
- // 解释:当超出指定内存值则移除最近最少用的图片内存
- public static int getDefaultLruCacheSize() {
- // 拿到最大内存
- final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
- // 拿到内存的八分之一来做图片内存缓存
- final int cacheSize = maxMemory / 8;
- return cacheSize;
- }
四、图片加载控件NetworkImageView
Volley还提供的加载图片的控件com.android.volley.NetworkImageView。
1.控件在被从父控件detach的时候,会自动取消网络请求的,
2.NetworkImageView还会根据你对图片设置的width和heigh自动压缩该图片不会产生多的内存
3.还有NetworkImageView在列表中使用不会图片错误
- private void networkImageViewUse(NetworkImageView iv, String url) {
- ImageLoader imLoader = new ImageLoader(mQueue, new BitmapLruCache());
- iv.setDefaultImageResId(R.drawable.ic_launcher);
- iv.setErrorImageResId(R.drawable.ic_launcher);
- iv.setImageUrl(url, imLoader);
- }
五、如何取消请求
- activity自动销毁时它会自定取消所有请求。
- 给请求设置标签:
request.setTag("My Tag");
取消所有指定标记的请求:
request.cancelAll("My Tag");
六、Volley请求流程
其中蓝色部分代表主线程,绿色部分代表缓存线程橙色部分代表网络线程。
1.主线程中调用RequestQueue的add()方法来添加一条网络请求
2.请求会先被加入到缓存队列当中
3.如果发现可以找到相应的缓存结果就直接读取缓存并解析,然后回调给主线程。
4.如果在缓存中没有找到结果,则将这条请求加入到网络请求队列中,然后处理发送HTTP请求,解析响应结果,写入缓存,并回调主线程。