转载自:https://www.cnblogs.com/liu37130/p/3902390.html

Volley是Google在2003年的I/O大会上推出的通信框架,结合了AsyncHttpClient和Universal- Image-Loader的优点——简化了http的使用 + 异步加载图片的神奇能力。Android中的Http实现主要有HttpUrlConnection和HttpClient两种,关于二者的选择 Google在Blog中表示推荐在姜饼小人(API level = 9)及以上的版本中使用Java的HttpUrlConnection而在之前的版本使用Apache的HttpClient,这在Volley这个框架 中也有明确的体现。

 

获取Volley

git clone https://android.googlesource.com/platform/frameworks/volley

把它编译成jar文件就可以加入libs了

 

一、简单的请求(以StringRequest为例)

  Http的通信最主要的部分应该就是发出请求和接收响应 了,所以Volley的比较核心的一个类就是RequestQueue,一个请求队列。它负责管理工作线程,读写缓存,和解析、分发响应(具体操作还是由 具体的类实现),即将发出的Http请求都会首先聚集在这里等待工作线程来实现请求。RequestQueue可以被看成一艘载满Http请求的航空母 舰,而工作线程就是弹射器喽。

  所以按照航母起飞飞机的步骤,我们可以猜到利用Volley进行Http通信的简单步骤:

    1.获取RequestQueue(得到一艘航母,可以是自己造的,也可以是委托别人造的,下面会提到)

    2.实例化一个Request(得到一架飞机,你也知道飞机又很多类型啦)

    3.将Request加入RequestQueue,等待工作线程将其发送出去(把飞机从机库升上起飞甲板,等待弹射器把它扔出去)

 

起飞侦察机-发出GET请求

  按照上面的步骤,第一步就是建立一个请求队列,最简单的方法就是用Volley.newRequestQueue(),这是一个特别方便的 静态方法,替我们默认实现了所有需要的东西(网络、缓存等,这些在Volley中都有默认实现),它会返回一个已经开始运行的 RequestQueue(相当于别人帮忙造了艘航母)。之后我们需要的只是设置好请求的响应监听接口,把请求加入到这个队列中就可以等着响应数据来敲门 了。下面是Google文档中的示例代码:

 

//初始化一个请求队列  RequestQueue queue = Volley.newRequestQueue(this);  String url ="http://www.google.com";    //根据给定的URL新建一个请求  StringRequest stringRequest = new StringRequest(Request.Method.GET, url,              new Response.Listener() {      @Override      public void onResponse(String response) {         //在这里操作UI组件是安全的,因为响应返回时这个函数会被post到UI线程来执行         // 在这里尽情蹂躏响应的String。     } }, new Response.ErrorListener() {     @Override     public void onErrorResponse(VolleyError error) {         // 出错了怎么办?凉拌!并且在这里拌。     }});// 把这个请求加入请求队列queue.add(stringRequest);

 

StringRequest是Request的具体实现之一,代表解析后的响应数据是一个字符串,相似的还有JsonRequest(包括 JsonObjectRequest和JsonArrayRequest两个可以使用的子类)、ImageRequest来满足基本的使用,用法大同小 异。主要是构造参数不一样,分别如下:

  1.public StringRequest(int method, String url, Listener listener,ErrorListener errorListener);     参数说明:从左到右分别是请求方法(都封装在Request中的Method接口内),请求URL,响应监听接口实例,错误监听接口实例。

  2.public JsonObjectRequest(int method, String url, JSONObject jsonRequest,Listener listener, ErrorListener errorListener);

     public JsonObjectRequest(String url, JSONObject jsonRequest, Listener listener,ErrorListener errorListener);

     参数说明:如果是GET请求的话,jsonRequest传入null就可以了,否则在未指明请求方法的情况下(也就是第二个构造函数)会默认为POST请求。其他同上。

  3.public JsonArrayRequest(String url, Listener listener, ErrorListener errorListener);

     参数说明:同上。

  4.public ImageRequest(String url, Response.Listener listener, int maxWidth, int maxHeight,Config decodeConfig, Response.ErrorListener errorListener);

     参数说明:decodeConfig是图片的颜色属性,下面的几个值都可以使用。

 

Bitmap.Config中的颜色属性(枚举类型)
ALPHA_8  
ARGB_4444 由于质量低,已经被弃用,推荐用ARGB_8888
ARGB_8888 每个像素用4byte存储
RGB_565 每个像素用2byte存储,红色占5位,绿色占6位,蓝色占5位

 

起飞战斗机-发出POST请求

  基本方式和上面一样,但是怎么装导弹,啊不,是怎么提交的数据呢?

Volley会在Request的请求方法是POST(还有PUT和PATCH)的情况下调用Request类(就是XXXRequest的父 类)的getParam()函数来获取参数,提前剧透,如果使用的是HttpUrlConnection的话,调用getParam()是在 HurlStatck中的addBodyIfExists()函数实现的,感兴趣的话可以去看一下哈。所以,POST请求像下面这样就可以了。

//初始化一个请求队列RequestQueue queue = Volley.newRequestQueue(this);String url ="http://www.google.com";//根据给定的URL新建一个请求StringRequest stringRequest = new StringRequest(Request.Method.POST, url,   new Response.Listener() {    @Override    public void onResponse(String response) {        // 在这里处理请求得到的String类型的响应   }}, new Response.ErrorListener() {    @Override    public void onErrorResponse(VolleyError error) {        // 在这里进行出错之后的处理   }}) {@Overrideprotected Map getParams() throws AuthFailureError {Map map = new HashMap();         map.put("params1", "value1");         map.put("params2", "value2");         return map };// 把这个请求加入请求队列queue.add(stringRequest);

 

 

后悔药-取消请求

  Request中有一个cancel()方法,调用这个就可以取消当前请求了,但是取消到哪一个层次就不一定了,但是Volley可以保证 响应处理函数(就是onResponse()和onErroeResponse())不会被调用。还有一个一起取消多个请求,就是在发出请求前调用 Request的setTag()方法为每个请求加一个标签,这个方法的参数是Object,所以我们可以使用任何类型作为标签。这样就可以调用 ReqiestQueue的cancelAll()函数取消一群标签了。比较常用的方法就是,将发出这个请求的Activity或者Fragment作为 标签,并在onStop()中调用cancelAll()。

 

二、使用ImageLoader加载图片

  ImageLoader 是一个可以实现图片异步加载的类,但已经不是继承与Request了。ImageLoader虽然是头神兽,但必须在主线程召唤它,否则会抛出错误 IllegalStateException,可能是因为ImageLoader在图片返回时要直接操作ImageView,在主线程里操作UI组件才是 安全的,so~

  用ImageLoader加载图片分三步

    1.创建ImageLoader

    2.获取一个ImageListener对象

    3.调用ImageLoader的get()方法获取图片

  ImageLoader的构造函数长成这样:public ImageLoader(RequestQueue queue, ImageCache imageCache);

所以实例化一个ImageLoader需要一个RequestQueue(之前建立的就行),还有一个ImageCache,这是一个 ImageLoader内部定义的接口,用来实现L1缓存——内存缓存(Volley在RequestQueue中已经实现了L2缓存——文件缓存)。 ImageLoader中并没有对传入的ImageCache在使用前判空的代码,传null进去会出错的。如果实在不想弄内存缓存,实现一个什么都不做 的ImageCache就好了。下面是代码:

 

ImageLoader imageLoader = new ImageLoader(mRequestQueue, new ImageCache() {      @Override      public void putBitmap(String url, Bitmap bitmap) {      }        @Override      public Bitmap getBitmap(String url) {          return null;      }  });//default_image是正在加载图片时占位用的//error_image是加载不成功时显示的图片ImageListener listener = ImageLoader.getImageListener(imageView, R.drawable.default_image, R.drawable.error_image); 15imageLoader.get("your image url", listener);

 

  除了ImageLoader之外Volley中还有一个Image加载的神器——NetworkImageView,使用步骤如下:

    1.在布局文件中加入控件,并在Java代码中获取实例

    2.设置default_image,error_image,图片URL,一个ImageLoader对象

  代码如下:

1 networkImageView = (NetworkImageView) findViewById(R.id.network_image_view); 2 networkImageView.setDefaultImageResId(R.drawable.default_image);  3 networkImageView.setErrorImageResId(R.drawable.error_image);4 networkImageView.setImageUrl("your image url", imageLoader);  

 

三、Google推荐的用法

  上面就是Volley的基本用法了,但是如果一个App需要频繁的网络通信的话,建立多个RequestQueue是件很奇怪的事儿(谁会 因为临时有飞机要在海上起飞就去新建一艘航母呢,这得多有钱啊),所以Google推荐我们只实例化一个RequestQueue来应付频繁的Http通 信,当然,要保证队列的寿命和App一样长。如何实现呢?Google又说了,不推荐在App的Application.onCretae()方法中实例 化一个RequestQueue(不过确实是个简单的方法哈),最好是建立一个单例模式的类,并把所有我们需要用到的Volley的瓶瓶罐罐都放进去,这 样显得更模块化。下面就是示例代码。这段代码中最重要的就是RequestQueue要用Application的Context实例化,要不然就会随着 Activity的生命周期不停重建。其实,像AsyncHttpClient中的纯静态使用方法也不错(详情见:http://loopj.com /android-async-http/)

PS:下面还实现了一个简单的ImageCache

 

private static MySingleton mInstance;    private RequestQueue mRequestQueue;    private ImageLoader mImageLoader;    private static Context mCtx;    private MySingleton(Context context) {        mCtx = context;        mRequestQueue = getRequestQueue();        mImageLoader = new ImageLoader(mRequestQueue,                new ImageLoader.ImageCache() {            private final LruCache                    cache = new LruCache(20);            @Override            public Bitmap getBitmap(String url) {                return cache.get(url);            }            @Override            public void putBitmap(String url, Bitmap bitmap) {                cache.put(url, bitmap);            }        });    }    public static synchronized MySingleton getInstance(Context context) {        if (mInstance == null) {            mInstance = new MySingleton(context);        }        return mInstance;    }    public RequestQueue getRequestQueue() {        if (mRequestQueue == null) {            // getApplicationContext()是关键, 它会避免            // Activity或者BroadcastReceiver带来的缺点.            mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());        }        return mRequestQueue;    }    public  void addToRequestQueue(Request req) {        getRequestQueue().add(req);    }    public ImageLoader getImageLoader() {        return mImageLoader;    }}

 

 

四、Volley是怎么管理请求的呢?

  RequestQueue会维护一个缓存调度线程(cache线程)和一个网络调度线程池(net线程)(注意,这是一池子线程),当一个 Request被加到队列中的时候,cache线程会把这个请求进行筛选:如果这个请求的内容可以在缓存中找到,cache线程会亲自解析相应内容,并分 发到主线程(UI)。如果缓存中没有,这个request就会被加入到另一个NetworkQueue,所有真正准备进行网络通信的request都在这 里,第一个可用的net线程会从NetworkQueue中拿出一个request扔向服务器。当响应数据到的时候,这个net线程会解析原始响应数据, 写入缓存,并把解析后的结果返回给主线程。如下图:

 

所以,读源码的话也可以把源码分成四层,如下图:(其余的类都可以归到“方便的工具类”中,比如ImageLoader,ClearCacheRequest等等)。

更多相关文章

  1. Android(安卓)移动开发TIPS小结4
  2. 阿里巴巴Android(安卓)技术规范文档知识点(个人认为有用的)
  3. Android(安卓)仿微信“正在输入...”效果快速实现
  4. Android通过URL获取网络资源
  5. Android(安卓)4.2 BT系统之蓝牙关闭过程全跟踪
  6. Android(安卓)Handler类
  7. 关于Android中定时周期执行线程方法
  8. android之fragment与fragment、activity与activity、fragment与a
  9. android multicast 多播(组播)问题

随机推荐

  1. Android设置TextView显示指定个数字符,超
  2. android的消息处理机制(图+源码分析)
  3. WebView高度自适应方案探究
  4. android中status bar 小结
  5. 学习之Android运行原理
  6. Android 动态库反汇编
  7. Android配置cocos2d-x开发环境
  8. Android(安卓)Binder设计与实现 – 设计
  9. Android(安卓)密钥保护
  10. 用Crosswalk的XWalkView做混合式App