Volley的初步了解
Posted _yegong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Volley的初步了解相关的知识,希望对你有一定的参考价值。
Volley的介绍
- Volley是什么?
- 2013年Google I/O大会上推出的网络请求和图片加载框架
- 其优点是api简单,性能优秀
- 非常适合数据量不大但是通信频繁的网络请求,而对于大数据量的操作,如文本下载,表现则没有那么好
- Volley内部仍然是使用的HttpURLConnection和HttpClient进行网络请求的,只是对于不同的android版本进行了响应的切换,2.3之前使用的HttpClient,2.3之后使用的是HttpURLConnection 这是因为在2.3版本之前,HttpURLConnection有一个很严重的bug,当开启请求的时候会造成线程池无法关闭。
- 为什么用Volley,相比XUtil,Volley解决了以下问题:
- 当用户finish当前的Activity的时候,而当前Activity正在进行网络请求,Volley支持取消网络请求
- 当用户旋转屏幕,Activity重新创建,那么同样的网络请求会从新发送,而Volley支持对重复的请求进行缓存
- 支持多样的网络请求返回封装
3. Volley的使用
-
首先,引入Volley类库,添加相关权限
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-
Volley中的核心类
- Request,请求类,有几个实现类
- StringRequest:请求的时候直接回来一个String
- JsonObjectRequest:请求的时候直接回来一个JsonObject
- JsonArrayRequest:请求的时候直接回来一个JsonArray
- ImageRequest:请求的时候直接回来一个Bitmap
- 自定义请求:一会我们会结合gson
- RequestQueue:请求队列,用来执行Request的
- ImageLoader:图片加载的类
- NetWorkImageView:继承自ImageView,可以直接加载网络图片
- Request,请求类,有几个实现类
-
创建请求队列RequestQueue
RequestQueue queue = Volley.newRequestQueue(this);
-
使用StringRequest进行请求
//2.创建网络请求 StringRequest stringRequest = new StringRequest(url, new Listener<String>() { @Override public void onResponse(String response) { tv_result.setText(response); } },new MyErrorListener()); //3.执行请求 queue.add(stringRequest);
-
使用JsonRequest进行请求
//1.创建JsonRequest请求 JsonObjectRequest joRequest = new JsonObjectRequest(url, null, new Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { tv_result.setText(response.toString()); } }, new MyErrorListener()); //2.执行请求 queue.add(joRequest);
-
使用JsonArrayRequest进行请求
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(listUrl, new Listener<JSONArray>() { @Override public void onResponse(JSONArray response) { tv_result.setText(response.toString()); } }, new MyErrorListener()); queue.add(jsonArrayRequest);
-
使用ImageRequest进行请求
ImageRequest imageRequest = new ImageRequest(imageUrl,new Listener<Bitmap>() { @Override public void onResponse(Bitmap response) { iv_result.setImageBitmap(response); } }, 200, 100, Config.RGB_565, new MyErrorListener()); queue.add(imageRequest);
4. 加载图片的压缩处理的核心
-
第一步: 从原图进行等宽高比的采样,采样的值最好是2的倍数,代码如下:
Options opts = new Options(); opts.inSampleSize = 4; Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fast, opts);
-
第二步: 根据图片的原始宽高比和控件的宽高比,科学的计算采样比例,代码如下:
Options opts = new Options(); opts.inJustDecodeBounds = true;//设置只解析图片的边界参数,即宽高 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fast, opts); //科学计算图片所需的采样比例 opts.inSampleSize = caculateSampleSize(opts.outWidth,opts.outHeight); opts.inJustDecodeBounds = false;//关闭标记,解析真实的图片 bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fast, opts); /** * 根据图片的原始宽高比和ImageView的宽高计算图片的采样比例 * @param outWidth * @param outHeight * @return */ private int caculateSampleSize(int outWidth, int outHeight) { int inSampleSize = 1; if(outWidth>outHeight){ //参考宽进行缩放 inSampleSize = outWidth/iv_result.getWidth();//1920/300 }else{ //参考高进行缩放 inSampleSize = outHeight/iv_result.getHeight(); } if(inSampleSize<1){ inSampleSize = 1; } return inSampleSize; }
-
第三步: 设置图片加载的渲染模式为Config.RGB_565,能降低一半内存:
opts.inPreferredConfig = Config.RGB_565
5. Volley中的ImageLoader使用以及内存缓存详解
-
使用ImageLoader加载图片
protected void loadImage() { ImageListener imageListener = ImageLoader.getImageListener(iv_result, R.drawable.ic_launcher, R.drawable.ic_launcher); MemoryCache imageCache = new MemoryCache(); ImageLoader imageLoader = new ImageLoader(queue, imageCache); imageLoader.get(imageUrl, imageListener); } /** * 图片内存缓存 * @author lxj * */ public class MemoryCache implements ImageCache{ private LruCache<String, Bitmap> lruCache; //app可用内存的8分之一 private int maxSize = (int) (Runtime.getRuntime().totalMemory()/8); public MemoryCache(){ lruCache = new LruCache<String, Bitmap>(maxSize){ @Override protected int sizeOf(String key, Bitmap value) { return value.getHeight()*value.getRowBytes(); } }; } @Override public Bitmap getBitmap(String url) { return lruCache.get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { lruCache.put(url, bitmap); } }
-
内存缓存详解
- 内存缓存的存储结构:一般是map,因为需要存取
-
在Android2.3之前还没有好的内存缓存策略出现,一般采用SoftRefrence对Bitmap进行包装,能尽量保证不会出现oom,几种引用的解释如下:
- 强引用 : 引用默认就是强引用, 即使内存oom, 也不会去回收对象
-
软应用:使用SoftRefrence去包装一个对象,内存不足的时候去回收对象,尽量保证不oom,代码如下:
HashMap<String, SoftReference<Bitmap>> map = new HashMap<String, SoftReference<Bitmap>>(); SoftReference<Bitmap> reference = map.get(url); Bitmap bitmap = reference.get();
- 弱引用:使用WeakReference保证一个对象,一般不用
- 在Android2.3之后Google提供了Lru算法的实现类,即LruCache,并推荐我们使用LruCache来实现图片的内存缓存,该类有效解决了Android中图片内存缓存的难题,常见几种内存缓存策略有:
- Least Frequently Used(LFU): 删除使用频率最少的
- Least Recently Used(LRU): 删除最近最少使用的
- First in First out(FIFO): 删除最先添加进来的
- Most Recently Used(MRU): 删除最近最多使用的
- LruCache内部实现原理(重点):
- 内部使用按照访问顺序排序的LinkedHashMap来存储数据
- 每次缓存命中,该条会按照元素的访问次数进行重新排序
- 并会判断缓存size是否超出maxSize,如果超出则移除最下方的数据,即最少使用的数据
- 我们必须实现sizeOf方法,用来指定每条数据的size,此处是返回bitmap的大小
- 了解XUtil等开源类库对图片内存缓存的实现
- 了解图片的磁盘缓存的实现DiskLruCache
6. Volley中的NetworlImageView的使用
MemoryCache imageCache = new MemoryCache(); ImageLoader imageLoader = new ImageLoader(queue, imageCache); net_imageview.setImageUrl(imageUrl, imageLoader);
7. 自定义Volley的Request
- 我们在开发中更多的是请求一个url,然后将结果解析为java bean,所以封装一个具有该功能的Request类,GosnRequest
-
代码如下:
protected void execGsonRequest() { GsonRequest<Stu> gsonRequest = new GsonRequest<Stu>(url, Stu.class, new Listener<Stu>() { @Override public void onResponse(Stu stu) { tv_result.setText(stu.toString()); } }, new MyErrorListener()); queue.add(gsonRequest); } public class GsonRequest<T> extends Request<T>{ private Class<T> clazz; private final Listener<T> mListener; public GsonRequest(String url,Class<T> clazz,Listener<T> listener, ErrorListener errorListener) { super(url, errorListener); mListener = listener; this.clazz = clazz; } @Override protected Response<T> parseNetworkResponse(NetworkResponse response) { String parsed; try { parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); } catch (UnsupportedEncodingException e) { parsed = new String(response.data); } //解析json,返回response T t = new Gson().fromJson(parsed,clazz ); return Response.success(t, HttpHeaderParser.parseCacheHeaders(response)); } @Override protected void deliverResponse(T response) { mListener.onResponse(response); } }
8. 使用Volley取消网络请求
-
给每个Request添加tag标识
stringRequest.setTag(this);
-
调用取消请求的方法
queue.cancelAll(this);
9. 使用Volley发送post请求,需要自己重写Request的getParams方法
public class PostReuqest extends StringRequest { private Map<String, String> params; public PostReuqest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) { super(url, listener, errorListener); } public PostReuqest(int method,String url, Response.Listener<String> listener, Response.ErrorListener errorListener) { super(method,url, listener, errorListener); } public void setParams(Map<String, String> params){ this.params = params; } @Override protected Map<String, String> getParams() throws AuthFailureError { return params; } } PostReuqest stringRequest = new PostReuqest(Request.Method.POST,Api.LOGIN, new com.android.volley.Response.Listener<String>() { @Override public void onResponse(String response) { text.setText(response); } }, new com.android.volley.Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }); HashMap<String,String> map = new HashMap<>(); map.put("username","hehehe"); map.put("password","12321"); stringRequest.setParams(map);
10. 对Volley进行二次封装
/** * Volley的二次封装类 * @author lxj * */ public class VolleyHelper { private RequestQueue requestQueue; MemoryCache imageCache = new MemoryCache(); private static VolleyHelper mInstance = null; private VolleyHelper(Context context){ requestQueue = Volley.newRequestQueue(context); } public static VolleyHelper get(Context context){ if(mInstance==null){ mInstance = new VolleyHelper(context); } return mInstance; } public <T> void executeRequest(Request<T> request){ requestQueue.add(request); } /** * 执行GsonRequest * @param url * @param clazz * @param listener * @param errorListener */ public <T> void executeGsonRequest(String url,Class<T> clazz,Listener<T> listener,ErrorListener errorListener){ GsonRequest<T> gsonRequest = new GsonRequest<T>(url, clazz, listener, errorListener); gsonRequest.setTag(url); requestQueue.add(gsonRequest); } /** * 取消请求 * @param tag */ public void cancelRequest(String tag){ requestQueue.cancelAll(tag); } /** * 加载图片 * @param imageUrl * @param imageView */ public void loadImage(String imageUrl,ImageView imageView){ ImageListener imageListener = ImageLoader.getImageListener(imageView, R.drawable.ic_launcher, R.drawable.ic_launcher); ImageLoader imageLoader = new ImageLoader(requestQueue, imageCache); imageLoader.get(imageUrl, imageListener); } }
以上是关于Volley的初步了解的主要内容,如果未能解决你的问题,请参考以下文章