Volley学习总结
1、概述
volley英文即是“齐射,并发”,是谷歌在2013年推出的网络通信库,有如下特点:
【1】通信更快,更简单
【2】Get、Post网络请求以及网络数据图像的高效的异步请求
【3】对网络优先级排序处理
【4】网络请求缓存,可以将上次数据进行简单缓存
【5】可以多级别取消请求
【6】可以和Activity生命周期的联动,在Activity销毁时可以结束网络请求操作
Volley在性能方面也进行了大幅度的调整,它的设计目标就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。
2、Volley框架使用之网络请求
【Volley的get和post请求方式的使用】
也是对android原生的get和psot进行了二次封装和优化,首先要挑选一个合适的请求对象
StringRequest:对请求数据结果类型不确定的情况下使用,该类型可以涵盖后面2种类型
JsonObjectRequest:确定是jsonObject时使用
JsonArrayRequest:确定是jsonArray时使用
【Volley的网络请求队列建立和取消】
首先要建立一个全局的请求队列,每次建立的请求加入到这个全局队列中,这样方便同意添加删除等管理
【Volley与Activity生命周期的联动】
将网络请求与Activity绑定在了一起,防止当Activity销毁时请求依然存在造成内存溢出,通常是将请求设置Tag标签,在onStop()中执行取消请求
【Volley的简单二次回调封装】
满足全局使用的一个方式可控,可自定义定制需求
在写代码之前首先要找到volley的jar包http://download.****.net/detail/inquisitive_plus/8488223#comment ,然后如何导入jar包到Android Studio中参考
http://jingyan.baidu.com/article/e6c8503c7190b7e54f1a1893.html
【代码实现】
这里给出一些关键代码,完整代码会在最后给出
Volley请求队列需要一个全局的,因此我们需要把他写到一个全局的Apllication中
<span style="font-size:18px;">public class MyApplication extends Application { //定义全局的网络请求队列 public static RequestQueue queues; @Override public void onCreate() { super.onCreate(); queues = Volley.newRequestQueue(getApplicationContext()); } //获取请求队列 public static RequestQueue getHttpQueues(){ return queues; } }</span>
然后在MAinActivity中给出StringResponse的方式,这里主要有四个参数 请求方式,url,请求成功回调函数,请求失败回调函数
Get方式URL直接携带参数
Get:String方式
<span style="font-size:18px;">private void Volley_StringGet() { /*这里使用StringRequets*/ String url = "http://ip.taobao.com/service/getIpInfo.php?ip=125.71.229.221"; StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String s) { Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { Toast.makeText(MainActivity.this, volleyError.toString(), Toast.LENGTH_LONG).show(); } }); /*请求对象设置Tag标签,并加入全局队列*/ request.setTag("StringGet"); MyApplication.getHttpQueues().add(request); }</span>Get:Json方式
<span style="font-size:18px;">private void Volley_JsonGet() { /*这里使用JsonRequets*/ String url = "http://ip.taobao.com/service/getIpInfo.php?ip=125.71.229.221"; JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject js) { Toast.makeText(MainActivity.this, js.toString(), Toast.LENGTH_LONG).show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { Toast.makeText(MainActivity.this, volleyError.toString(), Toast.LENGTH_LONG).show(); } }); /*请求对象设置Tag标签,并加入全局队列*/ request.setTag("JsonGet"); MyApplication.getHttpQueues().add(request); }</span>
Post:String方式
这里注意psot方式中URL不直接携带,StringPsot需要使用getParams()设置
<span style="font-size:18px;">private void Volley_StringPost() { /*这里使用StringRequets*/ String url = "http://ip.taobao.com/service/getIpInfo.php?"; StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() { @Override public void onResponse(String s) { Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { Toast.makeText(MainActivity.this, volleyError.toString(), Toast.LENGTH_LONG).show(); } }) { @Override protected Map<String, String> getParams() throws AuthFailureError { //这里需要设置post的参数 Map<String, String> hashMap = new HashMap<String, String>(); hashMap.put("ip", "125.71.229.221"); return hashMap; } }; //post请求需要单独实现 /*请求对象设置Tag标签,并加入全局队列*/ request.setTag("StringPost"); MyApplication.getHttpQueues().add(request); }</span>
Post :Json方式
这种方式首先需要HashMap来装参数,然后把新建jsonObj携带该参数即可使用,后来测试时发现这里使用的是淘宝IP查询接口不支持post方式,但是StringPost可以,jsonPost貌似不可以,不过操作方式是对的,你也可以换个其他结口试试。
<span style="font-size:18px;"> private void Volley_JsonPost() { /*这里使用JsonRequets*/ String url = "http://ip.taobao.com/service/getIpInfo.php?"; HashMap<String, String> hashMap = new HashMap<String, String>(); hashMap.put("ip", "125.71.229.222"); JSONObject jsonParams = new JSONObject(hashMap); JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, jsonParams, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject jsonObject) { Toast.makeText(MainActivity.this, jsonObject.toString(), Toast.LENGTH_LONG).show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { Toast.makeText(MainActivity.this, volleyError.toString(), Toast.LENGTH_LONG).show(); } }) { @Override public Map<String, String> getHeaders() { HashMap<String, String> headers = new HashMap<String, String>(); headers.put("Accept", "application/json"); headers.put("Content-Type", "application/json; charset=UTF-8"); return headers; } }; /*请求对象设置Tag标签,并加入全局队列*/ request.setTag("JsonPost"); MyApplication.getHttpQueues().add(request); }</span>
Volley与Activity进行联动:
当Activity进行关闭的时候需要在onStop方法处理,yourTag则是你设置关联的Tag
<span style="font-size:18px;"> @Override protected void onStop() { super.onStop(); MyApplication.getHttpQueues().cancelAll("yourTag"); }</span>
Volley的简单的二次封装我们将它写在utils包中
不如我们在请求失败都要加一个toast弹窗或者请求成功加一些其他的提示,需要在每次使用的地方都加上,比较麻烦,我们可以做一个二次封装以便全局统一使用
主要封装请求成功和请求失败的回调,这里以StringRequest为例
首先需要一个接口Interface
<span style="font-size:18px;">public abstract class VolleyStringReqItf { public Context context; public static Response.Listener<String> listener; public static Response.ErrorListener errorListener; //成功和失败的回调函数 public abstract void onMySuccess(String result); public abstract void onMyError(VolleyError error); public VolleyStringReqItf(Context context, Response.Listener<String> listener, Response.ErrorListener errorListener) { this.context = context; this.listener = listener; this.errorListener = errorListener; } public Response.Listener<String> loadingListener() { listener = new Response.Listener<String>() { @Override public void onResponse(String response) { onMySuccess(response); } }; return listener; } public Response.ErrorListener errorListener() { errorListener = new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { onMyError(volleyError); } }; return errorListener; } } </span>
然后是我们自定义的StringRequest,注释很详细
<span style="font-size:18px;">/** * Created by ELVIS on 2015/11/7. */ public class VolleyStrRequest { public static StringRequest stringRequest; public static Context context; public static void RequestStrGet(Context context, String url, String tag, VolleyStringReqItf vif) { //取消当前tag的volley请求防止重复请求 MyApplication.getHttpQueues().cancelAll(tag); stringRequest = new StringRequest(Request.Method.GET, url, vif.loadingListener(), vif.errorListener()); stringRequest.setTag(tag); MyApplication.getHttpQueues().add(stringRequest); //开启请求 MyApplication.getHttpQueues().start(); } public static void ReqestStrPost(Context context, String url, String tag, final HashMap<String, String> params, VolleyStringReqItf vif) { MyApplication.getHttpQueues().cancelAll(tag); stringRequest = new StringRequest(Request.Method.POST, url, vif.loadingListener(), vif.errorListener()) { @Override protected Map<String, String> getParams() throws AuthFailureError { return params; } }; stringRequest.setTag(tag); MyApplication.getHttpQueues().add(stringRequest); MyApplication.getHttpQueues().start(); } } </span>
这样使用起来就比较方便了,当然你也可以自定义自己的其他的VolleyRequest
3、Volley框架使用之加载图片的用法
【缓存功能简单介绍】
图片加载缓存主要使用了LruCache和ImageCache
【加载网络图片及监听】
主要是NetworkImageView
3.1、使用ImageRequest来请求网络图片
ImageRequest能够处理单张图片,返回bitmap。ImageReques通常有5个参数(url,成功listtener,加载图片宽度设置,加载图片高度设置,bitmap配置,失败listener),当加载图片宽高都为0表示按照原图大小加载
<span style="font-size:18px;"> private void initView() { iv_img = (ImageView) findViewById(R.id.iv_img); String url = " http://h.hiphotos.baidu.com/image/pic/item/d53f8794a4c27d1e3584e91b1fd5ad6edcc4384b.jpg"; ImageRequest request = new ImageRequest(url, new Response.Listener<Bitmap>() { @Override public void onResponse(Bitmap bitmap) { iv_img.setImageBitmap(bitmap); } }, 0, 0, Bitmap.Config.RGB_565, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { Toast.makeText(ImageActivity.this, "Failure", Toast.LENGTH_SHORT).show(); } }); MyApplication.getHttpQueues().add(request); }</span>
3.2、使用ImageLoader
ImageLoader这个类需要一个Request的实例以及一个ImageCache的实例。图片通过一个URL和一个ImageListener实例的get()方法就可以被加载。ImageLoader会检查ImageCache,而且如果缓存里没有图片就会从网络上获取。
Volley的ImageCache接口允许你使用你喜欢的Lru缓存实现。不幸的是Volley没有提供默认的实现。我们需要自己实现一个Bitcache
ImageCache接口有两个方法,getBitmap(String url)和putBitmap(String url, Bitmap bitmap).这两个方法足够简单直白,他们可以添加任何的缓存实现。
BItMapCache.java
<span style="font-size:18px;">public class BitmapCache implements ImageLoader.ImageCache { public LruCache<String, Bitmap> cache; public static final int MAX = 5 * 1024 * 1024; public BitmapCache() { cache = new LruCache<String, Bitmap>(MAX) { @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes() * value.getHeight(); } }; } @Override public Bitmap getBitmap(String s) { return cache.get(s); } @Override public void putBitmap(String s, Bitmap bitmap) { cache.put(s, bitmap); } } </span>
使用 ImageLoader,其中getImgListner
// imageView是一个ImageView实例
// ImageLoader.getImageListener的第二个参数是默认的图片resource id
// 第三个参数是请求失败时候的资源id,可以指定为0
<span style="font-size:18px;">private void initViewImgLoader() { Toast.makeText(ImageActivity.this, "ImgLoader方式", Toast.LENGTH_SHORT).show(); String url = "http://image.tianjimedia.com/uploadImages/2012/090/063N2L5N2HID.jpg"; //ImageLoader ImageLoader loader = new ImageLoader(MyApplication.getHttpQueues(), new BitmapCache()); ImageLoader.ImageListener listener = ImageLoader.getImageListener(iv_img, R.mipmap.ic_launcher, R.mipmap.ic_launcher); loader.get(url, listener); }</span>
3.3、使用NetworkImageView方式
NetworkImageView 继承了 ImageView,并且在内部添加了
<span style="font-size:18px;"> public void setImageUrl(String url, ImageLoader imageLoader) {} </span>
这里可以看出,使用NetworkImageView时候我们需要跟ImageLoader配合使用,而且还多了加载前默认图片和加载失败图片的方法
<span style="font-size:18px;">public void setDefaultImageResId(int defaultImage) { mDefaultImageId = defaultImage; } /** * Sets the error image resource ID to be used for this view in the event that the image * requested fails to load. */ public void setErrorImageResId(int errorImage) { mErrorImageId = errorImage; } </span>
使用代码:
<span style="font-size:18px;">private void initViewNetWorkImg() { Toast.makeText(ImageActivity.this, "NetWorkImg方式", Toast.LENGTH_SHORT).show(); netImgView = (NetworkImageView) findViewById(R.id.netWorkImg); String url = "http://new.aliyiyao.com/UpFiles/Image/2011/01/13/nc_129393721364387442.jpg"; ImageLoader loader = new ImageLoader(MyApplication.getHttpQueues(), new BitmapCache()); netImgView.setDefaultImageResId(R.mipmap.ic_launcher); netImgView.setErrorImageResId(R.mipmap.ic_launcher); netImgView.setImageUrl(url, loader); }</span>
demo地址http://download.****.net/detail/xsf50717/9251751
版权声明:如有转载请注明出处,谢谢~