volley实例

来源:互联网 发布:js中的短路表达式 编辑:程序博客网 时间:2024/05/25 23:29

1.自定义相关类


在Android_开源框架_Volley(Google IO 2013)源代码及内部实现过程分析一文中,简单概述了Volley框架内部实现过程。如想理解彻底应该熟悉android多线程通信机制(Android_Thread多线程_Handler,Message,Looper,MessageQueue多线程和特殊UI更新一文) ,JDK1.5提供的java.util.concurrent相关并发库和http访问网络(Android_HttpURLConnection_Get和Post请求[该框架使用] / Android_HttpClient_get请求post表单提交上传 一文)及图片缓存(Android_图片的三级缓存一文)相关知识

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. https://android.googlesource.com/platform/frameworks/volley  

(1).封装MyVolley类

在使用Volley之前,应该先进行初始化(可以自定义Application或者在SplashActivity中完成初始化),仅对外提供RequestQueue(添加request)和ImageLoader(下载图片)get方法!

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * MyVolley.java 
  3.  * @author zimo2013 
  4.  * @see http://blog.csdn.net/zimo2013 
  5.  *  
  6.  */  
  7. public class MyVolley {  
  8.     private static final String TAG = "MyVolley";  
  9.   
  10.     private static MyVolley instance;  
  11.     private static RequestQueue mRequestQueue;  
  12.     private static ImageLoader mImageLoader;  
  13.     private final static int RATE = 8// 默认分配最大空间的几分之一  
  14.   
  15.     private MyVolley(Context context) {  
  16.         mRequestQueue = Volley.newRequestQueue(context);  
  17.   
  18.         // 确定在LruCache中,分配缓存空间大小,默认程序分配最大空间的 1/8  
  19.         ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);  
  20.         int maxSize = manager.getMemoryClass() / RATE; // 比如 64M/8,单位为M  
  21.           
  22.         //BitmapLruCache自定义缓存class,该框架本身支持二级缓存,在BitmapLruCache封装一个软引用缓存  
  23.         mImageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache(1024*1024*maxSize));  
  24.   
  25.         LogUtil.i(TAG, "MyVolley初始化完成");  
  26.     }  
  27.   
  28.     /** 
  29.      * 初始化Volley相关对象,在使用Volley前应该完成初始化 
  30.      *  
  31.      * @param context 
  32.      */  
  33.     public static void init(Context context) {  
  34.         if (instance == null) {  
  35.             instance = new MyVolley(context);  
  36.         } else {  
  37.             LogUtil.w(TAG, "已经初始化过,不需要再次调用init()");  
  38.         }  
  39.     }  
  40.   
  41.     /** 
  42.      * 得到请求队列对象 
  43.      *  
  44.      * @return 
  45.      */  
  46.     public static RequestQueue getRequestQueue() {  
  47.         throwIfNotInit();  
  48.         return mRequestQueue;  
  49.     }  
  50.   
  51.     /** 
  52.      * 得到ImageLoader对象 
  53.      *  
  54.      * @return 
  55.      */  
  56.     public static ImageLoader getImageLoader() {  
  57.         throwIfNotInit();  
  58.         return mImageLoader;  
  59.     }  
  60.   
  61.     /** 
  62.      * 检查是否完成初始化 
  63.      */  
  64.     private static void throwIfNotInit() {  
  65.         if (instance == null) {// 尚未初始化  
  66.             throw new IllegalStateException("MyVolley尚未初始化,在使用前应该执行init()");  
  67.         }  
  68.     }  
  69. }  

(2).图片的三级缓存相关类

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * LruCache缓存管理类,该类实现了ImageCache接口,并实现了LruCache 
  3.  * 一旦bitmap对象从LruCache中被挤出,将会被放置在BitmapSoftRefCache中,再配合该框架本身支持的硬盘缓存,可以完成图片三级缓存 
  4.  *  
  5.  * BitmapLruCache.java 
  6.  * @author zimo2013 
  7.  * @see http://blog.csdn.net/zimo2013 
  8.  *  
  9.  */  
  10. public class BitmapLruCache extends LruCache<String, Bitmap> implements ImageCache {  
  11.     private static final String TAG = "BitmapLruCache";  
  12.   
  13.     private BitmapSoftRefCache softRefCache;  
  14.   
  15.     public BitmapLruCache(int maxSize) {  
  16.         super(maxSize);  
  17.         softRefCache = new BitmapSoftRefCache();  
  18.     }  
  19.   
  20.     @Override  
  21.     protected int sizeOf(String key, Bitmap value) {  
  22.         return value.getRowBytes() * value.getHeight();  
  23.     }  
  24.   
  25.     @Override  
  26.     protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {  
  27.         if (evicted) {  
  28.             LogUtil.i(TAG, "空间已满,缓存图片被挤出:" + key);  
  29.             // 将被挤出的bitmap对象,添加至软引用BitmapSoftRefCache  
  30.             softRefCache.putBitmap(key, oldValue);  
  31.         }  
  32.     }  
  33.   
  34.     /** 
  35.      * 得到缓存对象 
  36.      */  
  37.     @Override  
  38.     public Bitmap getBitmap(String url) {  
  39.         Bitmap bitmap = get(url);  
  40.         // 如果bitmap为null,尝试从软引用缓存中查找  
  41.         if (bitmap == null) {  
  42.             bitmap = softRefCache.getBitmap(url);  
  43.         } else {  
  44.             LogUtil.i(TAG, "LruCache命中:" + url);  
  45.         }  
  46.         return bitmap;  
  47.     }  
  48.   
  49.     /** 
  50.      * 添加缓存对象 
  51.      */  
  52.     @Override  
  53.     public void putBitmap(String url, Bitmap bitmap) {  
  54.         put(url, bitmap);  
  55.     }  
  56.   
  57. }  
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 软引用缓存管理类 
  3.  *  
  4.  * BitmapSoftRefCache.java 
  5.  * @author zimo2013 
  6.  * @see http://blog.csdn.net/zimo2013 
  7.  * 
  8.  */  
  9. public class BitmapSoftRefCache implements ImageCache{  
  10.     private static final String TAG = "BitmapSoftRefCache";  
  11.       
  12.     private LinkedHashMap<String, SoftReference<Bitmap>> map;  
  13.     public BitmapSoftRefCache() {  
  14.         map = new LinkedHashMap<String, SoftReference<Bitmap>>();  
  15.     }  
  16.   
  17.     /** 
  18.      * 从软引用集合中得到Bitmap对象 
  19.      */  
  20.     @Override  
  21.     public Bitmap getBitmap(String url) {  
  22.         Bitmap bitmap = null;  
  23.         SoftReference<Bitmap> softRef = map.get(url);  
  24.         if(softRef != null){  
  25.             bitmap = softRef.get();  
  26.             if(bitmap == null){  
  27.                 map.remove(url); //从map中移除  
  28.                 LogUtil.w(TAG, url+"对象已经被GC回收");  
  29.             }else{  
  30.                 LogUtil.i(TAG, "命中"+url);  
  31.             }  
  32.         }  
  33.         return bitmap;  
  34.     }  
  35.   
  36.     /** 
  37.      * 从软引用集合中添加bitmap对象 
  38.      */  
  39.     @Override  
  40.     public void putBitmap(String url, Bitmap bitmap) {  
  41.         SoftReference<Bitmap> softRef = new SoftReference<Bitmap>(bitmap);  
  42.         map.put(url, softRef);  
  43.     }  
  44.   
  45. }  

(3).图片错位

关于使用该框架造成图片错位问题,App使用了ImageLoader下载图片,当ListView滚动很快时,还是会发生错位!记得听别人提起过,使用该框架可以避免图片错位,但是结果还是会发生错位,查看源码并没有找到相关避免错位的措施,不知道是不是自己的使用方法不对,如您知晓,麻烦告知博主一下~

这里通过覆写ImageListener方法,通过ImageView为其指定Tag标签,防止图片错位,即比对下载完图片的ImageUrl和当前该ImageView的Tag是否相等~

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class ImageListenerFactory{  
  2.       
  3.     public static ImageListener getImageListener(final ImageView view,  
  4.             final int defaultImageResId, final int errorImageResId) {  
  5.         return new ImageListener() {  
  6.             @Override  
  7.             public void onErrorResponse(VolleyError error) {  
  8.                 if (errorImageResId != 0) {  
  9.                     view.setImageResource(errorImageResId);  
  10.                 }  
  11.             }  
  12.   
  13.             @Override  
  14.             public void onResponse(ImageContainer response, boolean isImmediate) {  
  15.                 if (response.getBitmap() != null) {  
  16.                       
  17.                     if(view.getTag().toString() == response.getRequestUrl()){  
  18.                         view.setImageBitmap(response.getBitmap());  
  19.                     }else{  
  20.                         LogUtil.i(TAG, "图片错位");  
  21.                     }  
  22.                 } else if (defaultImageResId != 0) {  
  23.                     view.setImageResource(defaultImageResId);  
  24.                 }  
  25.             }  
  26.         };  
  27.     }  
  28. }  

2.网络请求Request

(1).StringRequest

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public void testStringRequest(){  
  2.     String url = "http://www.baidu.com";  
  3.     //如果出现乱码,应该修改StringRequest的parseNetworkResponse()方法,指定byte[]-->String 编码  
  4.     MyVolley.getRequestQueue().add(new StringRequest(url, new Response.Listener<String>() {  
  5.   
  6.         @Override  
  7.         public void onResponse(String response) {  
  8.             System.out.println("response:"+response);  
  9.         }  
  10.     }, new Response.ErrorListener() {  
  11.   
  12.         @Override  
  13.         public void onErrorResponse(VolleyError error) {  
  14.               
  15.         }  
  16.     }));  
  17. }  

(2).JsonObjectRequest

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public void testJsonObjectRequest(){  
  2.     String url = "http://api.mobile.meituan.com/group/v1/deal/new-cate-list/android/4.1?cityId=1";  
  3.     //如果出现乱码,应该修改StringRequest的parseNetworkResponse()方法,指定byte[]-->String 编码  
  4.     MyVolley.getRequestQueue().add(  
  5.             new JsonObjectRequest(url,  
  6.                     null,   
  7.                     new Response.Listener<JSONObject>() {  
  8.   
  9.                         @Override  
  10.                         public void onResponse(JSONObject response) {  
  11.                             //该JSONObject为android系统提供的,如果希望得到一个已经解析完的对象,可以继承JsonRequest  
  12.                               
  13.                             //根据response,解析数据  
  14.                             try {  
  15.                                 System.out.println(response.get("stid"));  
  16.                             } catch (JSONException e) {  
  17.                                 e.printStackTrace();  
  18.                             }  
  19.                         }  
  20.                     },new Response.ErrorListener() {  
  21.   
  22.                         @Override  
  23.                         public void onErrorResponse(VolleyError error) {  
  24.                             System.out.println(error);  
  25.                         }  
  26.                     })  
  27.             );  
  28. }  

(3).自定义Request(Json解析)

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * MyJsonRequest.java 
  3.  *  
  4.  * @author zimo2013 
  5.  * @see http://blog.csdn.net/zimo2013 
  6.  */  
  7. public class MyJsonRequest<T> extends JsonRequest<T> {  
  8.     private Gson gson;  
  9.     private Class<T> clazz;  
  10.   
  11.     /** 
  12.      * 默认为GET请求方式 
  13.      * @param url 
  14.      * @param clazz     解析的class字节码 
  15.      * @param listener 请求成功监听器 
  16.      * @param errorListener 请求失败监听器 
  17.      */  
  18.     public MyJsonRequest(String url, Class<T> clazz, Listener<T> listener,  
  19.             ErrorListener errorListener) {  
  20.         this(Method.GET, url, null, clazz, listener, errorListener);  
  21.     }  
  22.   
  23.     /** 
  24.      *  
  25.      * @param method    请求方法 Use {@link com.android.volley.Request.Method}. 
  26.      * @param url 
  27.      * @param requestBody   如果是POST请求,可以提交form表单字符串,比如 name=zhangsan&age=20 
  28.      * @param clazz     解析的class字节码 
  29.      * @param listener 请求成功监听器 
  30.      * @param errorListener 请求失败监听器 
  31.      */  
  32.     public MyJsonRequest(int method, String url, String requestBody, Class<T> clazz,  
  33.             Listener<T> listener, ErrorListener errorListener) {  
  34.         super(method, url, null, listener, errorListener);  
  35.   
  36.         this.clazz = clazz;  
  37.         gson = new Gson();  
  38.     }  
  39.   
  40.     @Override  
  41.     protected Response<T> parseNetworkResponse(NetworkResponse response) {  
  42.         try {  
  43.             String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));  
  44.             return Response.success(gson.fromJson(json, clazz),  
  45.                     HttpHeaderParser.parseCacheHeaders(response));  
  46.         } catch (UnsupportedEncodingException e) {  
  47.             return Response.error(new ParseError(e));  
  48.         } catch (JsonSyntaxException e) {  
  49.             return Response.error(new ParseError(e));  
  50.         }  
  51.     }  
  52. }  
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public void testCustomRequest(){  
  2.     String urlString = "http://192.168.117.120:8080/news/json.html";  
  3.     MyJsonRequest<NewsInfo> request = new MyJsonRequest<NewsInfo>(urlString, NewsInfo.classnew Listener<NewsInfo>() {  
  4.   
  5.         @Override  
  6.         public void onResponse(NewsInfo response) {  
  7.             System.out.println(response.getClass());  
  8.             System.out.println(response);  
  9.         }  
  10.     }, null);  
  11.     MyVolley.getRequestQueue().add(request);  
  12. }  

(4).POST表单提交

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public void testRequestByPost(){  
  2.     String urlString = "http://192.168.43.240:8080/news/servlet/Post";  
  3.     StringRequest request = new StringRequest(Method.POST, urlString, new Listener<String>() {  
  4.   
  5.         @Override  
  6.         public void onResponse(String response) {  
  7.               
  8.         }  
  9.     }, new ErrorListener() {  
  10.   
  11.         @Override  
  12.         public void onErrorResponse(VolleyError error) {  
  13.               
  14.         }  
  15.     }){  
  16.         //覆写getBody()方法提交表单数据  
  17.         @Override  
  18.         public byte[] getBody() {  
  19.             return "name=zhangsan&age=15".getBytes();  
  20.         }  
  21.     };  
  22.     MyVolley.getRequestQueue().add(request);  
  23. }  

(5).ImageLoader异步加载图片(防错位)

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public void testImageLoader(){  
  2.     MyVolley.getImageLoader().get(imgUrl,   
  3.             //ImageListenerFactory为自定义类,封装后即可获取图片资源,完成UI更新  
  4.             ImageListenerFactory.getImageListener(//参考ImageLoader.getImageListener()  
  5.                     imageView,      // ImageView对象  
  6.                     R.drawable.ic_launcher, // 默认Image,如果不设应置为0  
  7.                     R.drawable.ic_launcher)); // 错误Image,如果不设应置为0  

0 0