一、Volley特点
通信更快,更简单(数据量不大,但网络通信频繁)
Get、Post网络请求及网络图像的高效率异步处理
排序(可以通过网络请求的优先级进行处理)
网络请求的缓存
多级别取消请求
和Activity生命周期的联动
二、为什么使用Volley
高效的Get/Post方式的数据请求交互
网络图片加载和缓存
三、Volley框架的使用
1.Volley的GET、Post
首先我们需要知道Volley自带了三种返回类型:
StringRequest:主要使用在对请求数据的返回类型不确定的情况下,StringRequest涵盖了JsonObjectRequest和JsonArrayRequest。
JsonObjectRequest:当确定请求数据的返回类型为JsonObject时使用。
JsonArrayRequest:当确定请求数据的返回类型为JsonArray时使用。
首先我们需要建立一个全局的请求队列,这样我们可以将一个请求加入到这个全局队列中,并可以管理整个APP的所有请求,包括取消一个或所有的请求。
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; } }
注意,我们需要在AndroidManifest中注册这个Application,记得加上网络权限
使用Get方法来请求数据
返回数据为StringRequest
private void volley_Get(){ String url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=......"; 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_SHORT).show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { Toast.makeText(MainActivity.this,volleyError.toString(),Toast.LENGTH_SHORT).show(); } }); request.setTag("abcGet"); MyApplication.getHttpQueues().add(request); }
这里面需要注意的便是构造StringRequest实例时传入的参数
第一个参数:请求数据的方法(Method.GET...)
第二个参数:请求数据的路径
第三个参数:请求成功时的回调方法(可以在里面处理数据)
第四个参数:请求失败时的回调方法
这下面还有一个方法
request.setTag();我们通过这个方法来为request设置标识,便于以后进行删除,查找请求的操作。
返回数据为JsonObjectRequest时
private void volley_Get(){ String url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=... "; JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject jsonObject) { Toast.makeText(MainActivity.this,jsonObject.toString(),Toast.LENGTH_SHORT).show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { Toast.makeText(MainActivity.this,volleyError.toString(),Toast.LENGTH_SHORT).show(); } }); request.setTag("abcGet"); MyApplication.getHttpQueues().add(request); }
使用方法同上,但要注意的是,与之不同的是多了第三个参数,这里是用来放,传参时Json格式数据的,如果用的是GET方法,传入参数在url中,可以将其设置为null。
使用Post请求数据
返回数据为StringRequest
public void vollye_Post(){ String url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm"; 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_SHORT).show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { Toast.makeText(MainActivity.this, volleyError.toString(), Toast.LENGTH_SHORT).show(); } }){ @Override protected Map<String, String> getParams() throws AuthFailureError { Map<String,String> hashMap = new HashMap<>(); hashMap.put("tel", "...... "); return hashMap; } }; request.setTag("abcPost"); MyApplication.getHttpQueues().add(request); }
Post请求的方法使用与Get方法相似,但它多了一个方法
getParams()这个方法用Map来获取你所需要Post的数据
返回数据为Json格式数据时
即将你所要传入的数据放到参数中即可,不用使用getParams()方法
private void volleyPost() { String url = "http://www.kuaidi100.com/query"; Map<String,String> map = new HashMap<>(); map.put("type","yuantong"); map.put("postid","....."); //将map转化为JSONObject对象 JSONObject jsonObject = new JSONObject(map); JsonObjectRequest request = new JsonObjectRequest(Method.POST, url, jsonObject, new Listener<JSONObject>() { @Override public void onResponse(JSONObject jsonObject) {//jsonObject为请求返回的Json格式数据 Toast.makeText(MainActivity.this,jsonObject.toString(),Toast.LENGTH_LONG).show(); } }, new ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { Toast.makeText(MainActivity.this,volleyError.toString(),Toast.LENGTH_LONG).show(); } }); //设置请求的Tag标签,可以在全局请求队列中通过Tag标签进行请求的查找 request.setTag("testPost"); //将请求加入全局队列中 MyApplication.getHttpQueues().add(request); }
2.与Avctivity生命周期联动
其实就是在Activity退出时候或销毁时候,取消对应的网络请求,避免网络请求在后台浪费资源,所以,我们一般在onStop()方法中通过之前设置的Tag取消网络请求:
@Override protected void onStop() { super.onStop(); //通过Tag标签取消请求队列中对应的全部请求 MyApplication.getHttpQueues().cancelAll(tag); }
3.Volley的二次封装
public abstract class VolleyInterface { public Context mContext; public static Response.Listener mListener; public static Response.ErrorListener mErrorListener; public VolleyInterface(Context context, Response.Listener listener, Response.ErrorListener errorListener) { mContext = context; mListener = listener; mErrorListener = errorListener; } public abstract void onSuccess(String result);//成功的回调 public abstract void onError(VolleyError error);//失败的回调 public Response.Listener successListener(){ mListener = new Response.Listener() { @Override public void onResponse(String response) { //我们可以在这里设置一些通用的方法,比如说比如一个显示百分比的加载框等等 onSuccess(response); } }; return mListener; } public Response.ErrorListener errorListener(){ mErrorListener = new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { //提示请求失败的对话框,避免重复书写 onError(error); } }; return mErrorListener; } }
public class VolleyRequest { public static StringRequest stringRequest; public static Context sContext; public static void RequestGet(Context context,String url, String tag, VolleyInterface vif){ sContext = context; MyApplication.getHttpQueues().cancelAll(tag);//如果之前存在,先取消,避免重复的请求 stringRequest = new StringRequest(Request.Method.GET,url,vif.successListener(),vif.errorListener()); stringRequest.setTag(tag); MyApplication.getHttpQueues().add(stringRequest); MyApplication.getHttpQueues().start(); } public static void RequestPost(Context context,String url,String tag, final Map<String,String> params,VolleyInterface vif){ MyApplication.getHttpQueues().cancelAll(tag); stringRequest = new StringRequest(url,vif.successListener(),vif.errorListener()){ @Override protected Map<String, String> getParams() throws AuthFailureError { return params; } }; stringRequest.setTag(tag); MyApplication.getHttpQueues().add(stringRequest); //MyApplication.getHttpQueues().start(); //建议不要手动调用 RequestQueue 的 start() 方法,引起的问题“经常会报com.android.volley.NoConnectionError: java.io.InterruptedIOException”,然后就内容加载失败。。。 因为在 Volley.newRequestQueue() 方法中,已经调用了 start() 方法。 } }
使用自己的封装方法
private void volley_Get(){ String url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443"; VolleyRequest.RequestGet(MainActivity.this, url, "abcGet", new VolleyAbstact(MainActivity.this,VolleyAbstact.mlistener,VolleyAbstact.mErrorListenerl) { @Override public void onMySuccess(String result) { Toast.makeText(MainActivity.this,result,Toast.LENGTH_SHORT).show(); } @Override public void onMyError(VolleyError error) { Toast.makeText(MainActivity.this,error.toString(),Toast.LENGTH_SHORT).show(); } }); }
4.获取网络图片
加载图片缓存
LruCache:这个类非常适合用来缓存图片,它的主要算法原理是把最近使用的对象用强引用存储在 LinkedHashMap 中,并且把最近最少使用的对象在缓存值达到预设定值之前从内存中移除。
ImageCache:Volley框架内部自己处理了DiskBasedCache硬盘缓存,但是没有处理LruCache内存缓存,因为一般在处理图片的问题上才更多的用到LruCache缓存,但是它提供了一个ImageCache接口供我们自己实现,该接口默认需要实现两个方法:getBitmap(String key)和putBitmap(String key, Bitmap bitmap)
加载图片与监听 ImageRequest:
ImageLoader:
NetworkImageView:
1.使用ImageRequest加载网络图片
ImageRequest request = new ImageRequest(url, new Response.Listener<Bitmap>() { @Override public void onResponse(Bitmap bitmap) { imageView.setImageBitmap(bitmap); } }, 0, 0, Bitmap.Config.RGB_565, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { imageView.setBackgroundResource(Color.BLACK); } }); MyApplication.getHttpQueues().add(request);
第一个参数:请求数据的路径
第二个参数:数据请求成功后的回调
第三、四个参数:允许的最大宽度、高度(0,0时指的是原图传入)
第五个参数:指定图片的格式
第六个参数:数据请求失败后的回调
2.使用ImageLoader加载图片
ImageLoader也可以用于加载网络上的图片,并且它的内部也是使用ImageRequest来实现的,不过ImageLoader明显要比ImageRequest更加高效,因为它不仅可以帮我们对图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求。
首先你需要建立一个缓存类
public class BitmapCache implements ImageLoader.ImageCache { public LruCache<String,Bitmap> cache; public int max = 10*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); } }
然后在MainActivity中
ImageLoader loader = new ImageLoader(MyApplication.getHttpQueues(),new BitmapCache()); ImageLoader.ImageListener listener = ImageLoader.getImageListener(imageView,Color.BLACK,Color.BLACK); loader.get(url,listener);
getImageView中
第一个参数:放置图片的控件
第二个参数:请求默认的图片
第三个参数:请求失败的图片
3.使用networkImageView辅助加载图片
实例化networkImageView后
String url = "https://www.baidu.com/img/bdlogo.png"; ImageLoader loader = new ImageLoader(MyApplication.getHttpQueues(),new BitmapCache()); networkImageView.setDefaultImageResId(Color.BLACK); networkImageView.setErrorImageResId(Color.BLUE); networkImageView.setImageUrl(url,loader);
第一个方法:请求默认的图片
第二个方法:请求失败的图片
第三个方法:请求得到的图片
四、总结:
到目前为止,本文就结束了,这篇文章主要讲了对Volley的粗糙使用,并未涉及太过复杂的知识。