Android_开源框架_Volley实例

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 plain copy 在CODE上查看代码片 派生到我的代码片
  1. https://android.googlesource.com/platform/frameworks/volley  

(1).封装MyVolley类

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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * MyVolley.java 
  3.  * @see http://blog.csdn.net/zimo2013 
  4.  * @author 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  
  20.                 .getSystemService(Context.ACTIVITY_SERVICE);  
  21.         int maxSize = manager.getMemoryClass() / RATE; // 比如 64M/8,单位为M  
  22.   
  23.         // BitmapLruCache自定义缓存class,android本身支持二级缓存,在BitmapLruCache封装一个软引用缓存  
  24.         mImageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache(  
  25.                 1024 * 1024 * maxSize));  
  26.   
  27.         Log.i(TAG, "MyVolley初始化完成");  
  28.     }  
  29.   
  30.     /** 
  31.      * 初始化Volley相关对象,在使用Volley前应该完成初始化 
  32.      *  
  33.      * @param context 
  34.      */  
  35.     public static void init(Context context) {  
  36.         if (instance == null) {  
  37.             instance = new MyVolley(context);  
  38.         }  
  39.     }  
  40.   
  41.     /** 
  42.      * 得到请求队列对象 
  43.      *  
  44.      * @return 
  45.      */  
  46.     private 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.     public static void addRequest(Request<?> request) {  
  62.         getRequestQueue().add(request);  
  63.     }  
  64.   
  65.     public static void getImage(String requestUrl, ImageView imageView) {  
  66.         getImage(requestUrl, imageView, 00);  
  67.     }  
  68.   
  69.     public static void getImage(String requestUrl, ImageView imageView,  
  70.             int defaultImageResId, int errorImageResId) {  
  71.         getImage(requestUrl, imageView, defaultImageResId, errorImageResId, 0,  
  72.                 0);  
  73.     }  
  74.   
  75.     public static void getImage(String requestUrl, ImageView imageView,  
  76.             int defaultImageResId, int errorImageResId, int maxWidth,  
  77.             int maxHeight) {  
  78.         imageView.setTag(requestUrl);  
  79.         getImageLoader().get(requestUrl, ImageListenerFactory.getImageListener(  
  80.                 imageView, defaultImageResId, errorImageResId), maxWidth,  
  81.                 maxHeight);  
  82.     }  
  83.   
  84.     /** 
  85.      * 检查是否完成初始化 
  86.      */  
  87.     private static void throwIfNotInit() {  
  88.         if (instance == null) {// 尚未初始化  
  89.             throw new IllegalStateException("MyVolley尚未初始化,在使用前应该执行init()");  
  90.         }  
  91.     }  
  92. }  

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

[java]  view plain copy 在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 plain copy 在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 plain copy 在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 plain copy 在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 plain copy 在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 plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * MyJsonRequest.java 
  3.  *  
  4.  * @author zimo2013 
  5.  */  
  6. public class MyJsonListRequest<T> extends JsonRequest<T> {  
  7.     private Gson gson;  
  8.     private Class<T> clazz;  
  9.     private String mKey;  
  10.   
  11.     /** 
  12.      * GET请求方式,直接将json字符串解析为 对应的clazz对象 
  13.      *  
  14.      * @param url 
  15.      *            请求url 
  16.      * @param clazz 
  17.      *            解析的class字节码 
  18.      * @param listener 
  19.      *            请求成功监听器 
  20.      * @param errorListener 
  21.      *            请求失败监听器 
  22.      */  
  23.     public MyJsonListRequest(String url, Class<T> clazz, Listener<T> listener,  
  24.             ErrorListener errorListener) {  
  25.         this(url, null, clazz, listener, errorListener);  
  26.     }  
  27.   
  28.     /** 
  29.      * GET请求方式,将json中的key对应的value解析为 对应的clazz对象 
  30.      *  
  31.      * @param url 
  32.      *            请求url 
  33.      * @param key 
  34.      *            取得指定的key,<b>NOTE:</b>只支持 root-key,所有子key均错误 
  35.      * @param clazz 
  36.      *            解析的class字节码 
  37.      * @param listener 
  38.      *            请求成功监听器 
  39.      * @param errorListener 
  40.      *            请求失败监听器 
  41.      */  
  42.     public MyJsonListRequest(String url, String key, Class<T> clazz,  
  43.             Listener<T> listener, ErrorListener errorListener) {  
  44.         this(Method.GET, url, null, key, clazz, listener, errorListener);  
  45.     }  
  46.   
  47.     /** 
  48.      *  
  49.      * @param method 
  50.      *            请求方法 Use {@link com.android.volley.Request.Method}. 
  51.      * @param url 
  52.      * @param requestBody 
  53.      *            如果是POST请求,可以提交form表单字符串,比如 name=zhangsan&age=20 
  54.      * @param key 
  55.      *            取得指定的key,<b>NOTE:</b>只支持 root-key,所有子key均错误 
  56.      * @param clazz 
  57.      *            解析的class字节码 
  58.      * @param listener 
  59.      *            请求成功监听器 
  60.      * @param errorListener 
  61.      *            请求失败监听器 
  62.      */  
  63.     public MyJsonListRequest(int method, String url, String requestBody,  
  64.             String key, Class<T> clazz, Listener<T> listener,  
  65.             ErrorListener errorListener) {  
  66.         super(method, url, null, listener, errorListener);  
  67.   
  68.         this.clazz = clazz;  
  69.         mKey = key;  
  70.         gson = new Gson();  
  71.   
  72.     }  
  73.   
  74.     @Override  
  75.     protected Response<T> parseNetworkResponse(NetworkResponse response) {  
  76.         try {  
  77.             String json = new String(response.data,  
  78.                     HttpHeaderParser.parseCharset(response.headers));  
  79.             T t = null;  
  80.             if(mKey == null){  
  81.                 t = gson.fromJson(json, clazz);  
  82.             }else{  
  83.                 JsonObject jsonObject = gson.fromJson(json, JsonObject.class);  
  84.                 t = gson.fromJson(jsonObject.get(mKey), clazz);  
  85.             }  
  86.             return Response.success(t,  
  87.                     HttpHeaderParser.parseCacheHeaders(response));  
  88.         } catch (UnsupportedEncodingException e) {  
  89.             return Response.error(new ParseError(e));  
  90.         } catch (JsonSyntaxException e) {  
  91.             return Response.error(new ParseError(e));  
  92.         }  
  93.     }  
  94. }  
[java]  view plain copy 在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 plain copy 在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 plain copy 在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  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值