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类库,添加相关权限

    1. <uses-permission android:name="android.permission.INTERNET"/>
    2. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    3. <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,可以直接加载网络图片
  • 创建请求队列RequestQueue

    1. RequestQueue queue = Volley.newRequestQueue(this);
  • 使用StringRequest进行请求

    1. //2.创建网络请求
    2. StringRequest stringRequest = new StringRequest(url, new Listener<String>() {
    3. @Override
    4. public void onResponse(String response) {
    5. tv_result.setText(response);
    6. }
    7. },new MyErrorListener());
    8. //3.执行请求
    9. queue.add(stringRequest);
  • 使用JsonRequest进行请求

    1. //1.创建JsonRequest请求
    2. JsonObjectRequest joRequest = new JsonObjectRequest(url, null, new Listener<JSONObject>() {
    3. @Override
    4. public void onResponse(JSONObject response) {
    5. tv_result.setText(response.toString());
    6. }
    7. }, new MyErrorListener());
    8. //2.执行请求
    9. queue.add(joRequest);
  • 使用JsonArrayRequest进行请求

    1. JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(listUrl, new Listener<JSONArray>() {
    2. @Override
    3. public void onResponse(JSONArray response) {
    4. tv_result.setText(response.toString());
    5. }
    6. }, new MyErrorListener());
    7. queue.add(jsonArrayRequest);
  • 使用ImageRequest进行请求

    1. ImageRequest imageRequest = new ImageRequest(imageUrl,new Listener<Bitmap>() {
    2. @Override
    3. public void onResponse(Bitmap response) {
    4. iv_result.setImageBitmap(response);
    5. }
    6. }, 200, 100, Config.RGB_565, new MyErrorListener());
    7. queue.add(imageRequest);

4. 加载图片的压缩处理的核心

  • 第一步: 从原图进行等宽高比的采样,采样的值最好是2的倍数,代码如下:

    1. Options opts = new Options();
    2. opts.inSampleSize = 4;
    3. Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fast, opts);
  • 第二步: 根据图片的原始宽高比和控件的宽高比,科学的计算采样比例,代码如下:

    1. Options opts = new Options();
    2. opts.inJustDecodeBounds = true;//设置只解析图片的边界参数,即宽高
    3. Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fast, opts);
    4. //科学计算图片所需的采样比例
    5. opts.inSampleSize = caculateSampleSize(opts.outWidth,opts.outHeight);
    6.  
    7. opts.inJustDecodeBounds = false;//关闭标记,解析真实的图片
    8. bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fast, opts);
    9.  
    10. /**
    11. * 根据图片的原始宽高比和ImageView的宽高计算图片的采样比例
    12. * @param outWidth
    13. * @param outHeight
    14. * @return
    15. */
    16. private int caculateSampleSize(int outWidth, int outHeight) {
    17. int inSampleSize = 1;
    18. if(outWidth>outHeight){
    19. //参考宽进行缩放
    20. inSampleSize = outWidth/iv_result.getWidth();//1920/300
    21. }else{
    22. //参考高进行缩放
    23. inSampleSize = outHeight/iv_result.getHeight();
    24. }
    25. if(inSampleSize<1){
    26. inSampleSize = 1;
    27. }
    28. return inSampleSize;
    29. }
  • 第三步: 设置图片加载的渲染模式为Config.RGB_565,能降低一半内存:

    1. opts.inPreferredConfig = Config.RGB_565

5. Volley中的ImageLoader使用以及内存缓存详解

  • 使用ImageLoader加载图片

    1. protected void loadImage() {
    2. ImageListener imageListener = ImageLoader.getImageListener(iv_result, R.drawable.ic_launcher, R.drawable.ic_launcher);
    3. MemoryCache imageCache = new MemoryCache();
    4. ImageLoader imageLoader = new ImageLoader(queue, imageCache);
    5. imageLoader.get(imageUrl, imageListener);
    6. }
    7. /**
    8. * 图片内存缓存
    9. * @author lxj
    10. *
    11. */
    12. public class MemoryCache implements ImageCache{
    13. private LruCache<String, Bitmap> lruCache;
    14. //app可用内存的8分之一
    15. private int maxSize = (int) (Runtime.getRuntime().totalMemory()/8);
    16. public MemoryCache(){
    17. lruCache = new LruCache<String, Bitmap>(maxSize){
    18. @Override
    19. protected int sizeOf(String key, Bitmap value) {
    20. return value.getHeight()*value.getRowBytes();
    21. }
    22. };
    23. }
    24. @Override
    25. public Bitmap getBitmap(String url) {
    26. return lruCache.get(url);
    27. }
    28.  
    29. @Override
    30. public void putBitmap(String url, Bitmap bitmap) {
    31. lruCache.put(url, bitmap);
    32. }
    33. }
  • 内存缓存详解

    • 内存缓存的存储结构:一般是map,因为需要存取
    • 在Android2.3之前还没有好的内存缓存策略出现,一般采用SoftRefrence对Bitmap进行包装,能尽量保证不会出现oom,几种引用的解释如下:

      • 强引用 : 引用默认就是强引用, 即使内存oom, 也不会去回收对象
      • 软应用:使用SoftRefrence去包装一个对象,内存不足的时候去回收对象,尽量保证不oom,代码如下:

        1. HashMap<String, SoftReference<Bitmap>> map = new HashMap<String, SoftReference<Bitmap>>();
        2. SoftReference<Bitmap> reference = map.get(url);
        3. 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的使用

  1. MemoryCache imageCache = new MemoryCache();
  2. ImageLoader imageLoader = new ImageLoader(queue, imageCache);
  3. net_imageview.setImageUrl(imageUrl, imageLoader);

7. 自定义Volley的Request

  • 我们在开发中更多的是请求一个url,然后将结果解析为java bean,所以封装一个具有该功能的Request类,GosnRequest
  • 代码如下:

    1. protected void execGsonRequest() {
    2. GsonRequest<Stu> gsonRequest = new GsonRequest<Stu>(url, Stu.class, new Listener<Stu>() {
    3. @Override
    4. public void onResponse(Stu stu) {
    5. tv_result.setText(stu.toString());
    6. }
    7. }, new MyErrorListener());
    8. queue.add(gsonRequest);
    9. }
    10. public class GsonRequest<T> extends Request<T>{
    11. private Class<T> clazz;
    12. private final Listener<T> mListener;
    13. public GsonRequest(String url,Class<T> clazz,Listener<T> listener, ErrorListener errorListener) {
    14. super(url, errorListener);
    15. mListener = listener;
    16. this.clazz = clazz;
    17. }
    18. @Override
    19. protected Response<T> parseNetworkResponse(NetworkResponse response) {
    20. String parsed;
    21. try {
    22. parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
    23. } catch (UnsupportedEncodingException e) {
    24. parsed = new String(response.data);
    25. }
    26. //解析json,返回response
    27. T t = new Gson().fromJson(parsed,clazz );
    28. return Response.success(t, HttpHeaderParser.parseCacheHeaders(response));
    29. }
    30. @Override
    31. protected void deliverResponse(T response) {
    32. mListener.onResponse(response);
    33. }
    34. }

8. 使用Volley取消网络请求

  • 给每个Request添加tag标识

    1. stringRequest.setTag(this);
  • 调用取消请求的方法

    1. queue.cancelAll(this);

9. 使用Volley发送post请求,需要自己重写Request的getParams方法

  1. public class PostReuqest extends StringRequest {
  2. private Map<String, String> params;
  3. public PostReuqest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
  4. super(url, listener, errorListener);
  5. }
  6. public PostReuqest(int method,String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
  7. super(method,url, listener, errorListener);
  8. }
  9. public void setParams(Map<String, String> params){
  10. this.params = params;
  11. }
  12. @Override
  13. protected Map<String, String> getParams() throws AuthFailureError {
  14. return params;
  15. }
  16. }
  17.  
  18. PostReuqest stringRequest = new PostReuqest(Request.Method.POST,Api.LOGIN, new com.android.volley.Response.Listener<String>() {
  19. @Override
  20. public void onResponse(String response) {
  21. text.setText(response);
  22. }
  23. }, new com.android.volley.Response.ErrorListener() {
  24. @Override
  25. public void onErrorResponse(VolleyError error) {
  26.  
  27. }
  28. });
  29. HashMap<String,String> map = new HashMap<>();
  30. map.put("username","hehehe");
  31. map.put("password","12321");
  32. stringRequest.setParams(map);

10. 对Volley进行二次封装

  1. /**
  2. * Volley的二次封装类
  3. * @author lxj
  4. *
  5. */
  6. public class VolleyHelper {
  7. private RequestQueue requestQueue;
  8. MemoryCache imageCache = new MemoryCache();
  9. private static VolleyHelper mInstance = null;
  10. private VolleyHelper(Context context){
  11. requestQueue = Volley.newRequestQueue(context);
  12.  
  13. }
  14. public static VolleyHelper get(Context context){
  15. if(mInstance==null){
  16. mInstance = new VolleyHelper(context);
  17. }
  18. return mInstance;
  19. }
  20. public <T> void executeRequest(Request<T> request){
  21. requestQueue.add(request);
  22. }
  23. /**
  24. * 执行GsonRequest
  25. * @param url
  26. * @param clazz
  27. * @param listener
  28. * @param errorListener
  29. */
  30. public <T> void executeGsonRequest(String url,Class<T> clazz,Listener<T> listener,ErrorListener errorListener){
  31. GsonRequest<T> gsonRequest = new GsonRequest<T>(url, clazz, listener, errorListener);
  32. gsonRequest.setTag(url);
  33. requestQueue.add(gsonRequest);
  34. }
  35. /**
  36. * 取消请求
  37. * @param tag
  38. */
  39. public void cancelRequest(String tag){
  40. requestQueue.cancelAll(tag);
  41. }
  42. /**
  43. * 加载图片
  44. * @param imageUrl
  45. * @param imageView
  46. */
  47. public void loadImage(String imageUrl,ImageView imageView){
  48. ImageListener imageListener = ImageLoader.getImageListener(imageView, R.drawable.ic_launcher, R.drawable.ic_launcher);
  49. ImageLoader imageLoader = new ImageLoader(requestQueue, imageCache);
  50. imageLoader.get(imageUrl, imageListener);
  51. }
  52. }

Volley的初步了解的更多相关文章

  1. Android网络编程系列之Volley总结

    前言 Volley的中文翻译为“齐射.并发”,是在2013年的Google大会上发布的一款Android平台网络通信库,具有网络请求的处理.小图片的异步加载和缓存等功能,能够帮助 Android AP ...

  2. 小记:对Android网络下载工具的初步封装!(包括json,字符串下载(volley),和图片下载(glide))

    import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkIn ...

  3. Android 学习笔记之Volley开源框架解析(二)

    PS:Volley已经学完,可以安心的写一下博客总结一下了... 学习内容: 1.Request的完整封装... 2.RetryPolicy,DefaultRetryPolicy(请求重试策略源码解析 ...

  4. Android网络通信Volley框架源代码浅析(三)

    尊重原创 http://write.blog.csdn.net/postedit/26002961 通过前面浅析(一)和浅析(二)的分析.相信大家对于Volley有了初步的认识,可是假设想更深入的理解 ...

  5. 开源框架Volley的使用《二》[NetWorkImageView&&LruCache&ImageLoader]

    转载本专栏每一篇博客请注明转载出处地址,尊重原创.此博客转载链接地址:小杨的博客    http://blog.csdn.net/qq_32059827/article/details/5278849 ...

  6. 一口一口吃掉Volley(二)

    欢迎访问我的个人博客转发请注明出处:http://www.wensibo.top/2017/02/17/一口一口吃掉Volley(二)/ 相信看了第一篇教程之后,你应该会对Volley有一个初步的了解 ...

  7. 移动端之Android开发的几种方式的初步体验

    目前越来越多的移动端混合开发方式,下面列举的大多数我都略微的尝试过,就初步的认识写个简单的心得: 开发方式 开发环境 是否需要AndroidSDK 支持跨平台 开发语言&技能 MUI Win+ ...

  8. CSharpGL(29)初步封装Texture和Framebuffer

    +BIT祝威+悄悄在此留下版了个权的信息说: CSharpGL(29)初步封装Texture和Framebuffer +BIT祝威+悄悄在此留下版了个权的信息说: Texture和Framebuffe ...

  9. 快速Android开发系列网络篇之Volley

    Volley是Google推出的一个网络请求库,已经被放到了Android源码中,地址在这里,先看使用方法 RequestQueue mRequestQueue = Volley.newRequest ...

随机推荐

  1. C#中list比数组效率低多少

    对于List,即长度不确定的数组而言,十万笔数据*12倍,就是120万笔数据,只需要93ms左右   换成了二维数组,效果也是差不多,78ms,可见list的效率只比double差一点点  

  2. css 滤镜之Gradient

      CreateTime--2017年12月26日11:09:14 Author:Marydon ie滤镜特效之Gradient 作用: 用于设置渐变背景色 使用条件: IE9及以下版本不支持属性ba ...

  3. 【Android数据存储】- File

    个人学习整理.如有不足之处,请不吝不吝赐教. 转载请注明:@CSU-Max 读写本应用程序数据目录中的文件        此种方法读写的文件在/data/data/<应用程序包名>中   ...

  4. php事务操作示例

    <?php //数据库连接 $conn = mysql_connect('localhost', 'root', '');mysql_select_db('test', $conn); /* 支 ...

  5. html2canvas 导出包含滚动条的内容

    import html2canvas from 'html2canvas'; exportPDF() { // 导出为 pdf let dom = document.querySelector('yo ...

  6. 将前端js异步调用的多个服务合并为一个前端服务

    将前端js异步调用的多个服务合并为一个前端服务 1. 减少前端js异步请求的次数改善浏览体验 2. 方便地针对单个接口做异常降级处理

  7. css3动画应用-音乐唱片旋转播放特效

    css3动画应用-音乐唱片旋转播放特效 核心点: 1.设置图片为圆形居中,使图片一直不停旋转. 2.文字标题(潘玮柏--反转地球)一直从左到右不停循环移动. 3.点击图标,音乐暂停,图片停止旋转:点击 ...

  8. 深入理解Java执行时数据区

    前情回想 在本专栏的前12篇博客中. 我们主要大致介绍了什么是JVM, 而且具体介绍了class文件的格式. 对于深入理解Java, 或者深入理解运行于JVM上的其它语言, 深入理解class文件格式 ...

  9. 迭代器-iteration

    class CoffrrIterator implements Iterator<Coffee> { int cunt = size; public boolean hasNext() { ...

  10. lucene DocValues——本质是为通过docID查找某field的值

    什么是docValues? docValues是一种记录doc字段值的一种形式,在例如在结果排序和统计Facet查询时,需要通过docid取字段值的场景下是非常高效的. 为什么要使用docValues ...