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_图片的三级缓存一文)相关知识

  1. https://android.googlesource.com/platform/frameworks/volley
复制代码

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

  1. /**
  2. * MyVolley.java
  3. * @author zimo2013
  4. * [url=home.php?mod=space&uid=189949]@See[/url] http://blog.csdn.net/zimo2013
  5. *
  6. */
  7. public class MyVolley {
  8.         private static final String TAG = "MyVolley";

  9.         private static MyVolley instance;
  10.         private static RequestQueue mRequestQueue;
  11.         private static ImageLoader mImageLoader;
  12.         private final static int RATE = 8; // 默认分配最大空间的几分之一

  13.         private MyVolley(Context context) {
  14.                 mRequestQueue = Volley.newRequestQueue(context);

  15.                 // 确定在LruCache中,分配缓存空间大小,默认程序分配最大空间的 1/8
  16.                 ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
  17.                 int maxSize = manager.getMemoryClass() / RATE; // 比如 64M/8,单位为M
  18.                
  19.                 //BitmapLruCache自定义缓存class,该框架本身支持二级缓存,在BitmapLruCache封装一个软引用缓存
  20.                 mImageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache(1024*1024*maxSize));

  21.                 LogUtil.i(TAG, "MyVolley初始化完成");
  22.         }

  23.         /**
  24.          * 初始化Volley相关对象,在使用Volley前应该完成初始化
  25.          *
  26.          * @param context
  27.          */
  28.         public static void init(Context context) {
  29.                 if (instance == null) {
  30.                         instance = new MyVolley(context);
  31.                 } else {
  32.                         LogUtil.w(TAG, "已经初始化过,不需要再次调用init()");
  33.                 }
  34.         }

  35.         /**
  36.          * 得到请求队列对象
  37.          *
  38.          * @return
  39.          */
  40.         public static RequestQueue getRequestQueue() {
  41.                 throwIfNotInit();
  42.                 return mRequestQueue;
  43.         }

  44.         /**
  45.          * 得到ImageLoader对象
  46.          *
  47.          * @return
  48.          */
  49.         public static ImageLoader getImageLoader() {
  50.                 throwIfNotInit();
  51.                 return mImageLoader;
  52.         }

  53.         /**
  54.          * 检查是否完成初始化
  55.          */
  56.         private static void throwIfNotInit() {
  57.                 if (instance == null) {// 尚未初始化
  58.                         throw new IllegalStateException("MyVolley尚未初始化,在使用前应该执行init()");
  59.                 }
  60.         }
  61. }
复制代码

(2).图片的三级缓存相关类
  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.         private BitmapSoftRefCache softRefCache;

  13.         public BitmapLruCache(int maxSize) {
  14.                 super(maxSize);
  15.                 softRefCache = new BitmapSoftRefCache();
  16.         }

  17.         @Override
  18.         protected int sizeOf(String key, Bitmap value) {
  19.                 return value.getRowBytes() * value.getHeight();
  20.         }

  21.         @Override
  22.         protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
  23.                 if (evicted) {
  24.                         LogUtil.i(TAG, "空间已满,缓存图片被挤出:" + key);
  25.                         // 将被挤出的bitmap对象,添加至软引用BitmapSoftRefCache
  26.                         softRefCache.putBitmap(key, oldValue);
  27.                 }
  28.         }

  29.         /**
  30.          * 得到缓存对象
  31.          */
  32.         @Override
  33.         public Bitmap getBitmap(String url) {
  34.                 Bitmap bitmap = get(url);
  35.                 // 如果bitmap为null,尝试从软引用缓存中查找
  36.                 if (bitmap == null) {
  37.                         bitmap = softRefCache.getBitmap(url);
  38.                 } else {
  39.                         LogUtil.i(TAG, "LruCache命中:" + url);
  40.                 }
  41.                 return bitmap;
  42.         }

  43.         /**
  44.          * 添加缓存对象
  45.          */
  46.         @Override
  47.         public void putBitmap(String url, Bitmap bitmap) {
  48.                 put(url, bitmap);
  49.         }

  50. }
复制代码
  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.          * 从软引用集合中得到Bitmap对象
  18.          */
  19.         @Override
  20.         public Bitmap getBitmap(String url) {
  21.                 Bitmap bitmap = null;
  22.                 SoftReference<Bitmap> softRef = map.get(url);
  23.                 if(softRef != null){
  24.                         bitmap = softRef.get();
  25.                         if(bitmap == null){
  26.                                 map.remove(url); //从map中移除
  27.                                 LogUtil.w(TAG, url+"对象已经被GC回收");
  28.                         }else{
  29.                                 LogUtil.i(TAG, "命中"+url);
  30.                         }
  31.                 }
  32.                 return bitmap;
  33.         }

  34.         /**
  35.          * 从软引用集合中添加bitmap对象
  36.          */
  37.         @Override
  38.         public void putBitmap(String url, Bitmap bitmap) {
  39.                 SoftReference<Bitmap> softRef = new SoftReference<Bitmap>(bitmap);
  40.                 map.put(url, softRef);
  41.         }

  42. }
复制代码

(3).图片错位
关于使用该框架造成图片错位问题,App使用了ImageLoader下载图片,当ListView滚动很快时,还是会发生错位!记得听别人提起过,使用该框架可以避免图片错位,但是结果还是会发生错位,查看源码并没有找到相关避免错位的措施,不知道是不是自己的使用方法不对,如您知晓,麻烦告知博主一下~这里通过覆写ImageListener方法,通过ImageView为其指定Tag标签,防止图片错位,即比对 下载完图片的ImageUrl和当前该 ImageView的Tag是否相等~
  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.             @Override
  13.             public void onResponse(ImageContainer response, boolean isImmediate) {
  14.                 if (response.getBitmap() != null) {
  15.                         
  16.                     if(view.getTag().toString() == response.getRequestUrl()){
  17.                             view.setImageBitmap(response.getBitmap());
  18.                     }else{
  19.                             LogUtil.i(TAG, "图片错位");
  20.                     }
  21.                 } else if (defaultImageResId != 0) {
  22.                     view.setImageResource(defaultImageResId);
  23.                 }
  24.             }
  25.         };
  26.     }
  27. }
复制代码

2.网络请求Request
(1).StringRequest
  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.                 @Override
  6.                 public void onResponse(String response) {
  7.                         System.out.println("response:"+response);
  8.                 }
  9.         }, new Response.ErrorListener() {

  10.                 @Override
  11.                 public void onErrorResponse(VolleyError error) {
  12.                         
  13.                 }
  14.         }));
  15. }
复制代码

(2).JsonObjectRequest
  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.                                                 @Override
  9.                                                 public void onResponse(JSONObject response) {
  10.                                                         //该JSONObject为android系统提供的,如果希望得到一个已经解析完的对象,可以继承JsonRequest
  11.                                                         
  12.                                                         //根据response,解析数据
  13.                                                         try {
  14.                                                                 System.out.println(response.get("stid"));
  15.                                                         } catch (JSONException e) {
  16.                                                                 e.printStackTrace();
  17.                                                         }
  18.                                                 }
  19.                                         },new Response.ErrorListener() {

  20.                                                 @Override
  21.                                                 public void onErrorResponse(VolleyError error) {
  22.                                                         System.out.println(error);
  23.                                                 }
  24.                                         })
  25.                         );
  26. }
复制代码

(3).自定义Request(Json解析)
  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.          * 默认为GET请求方式
  12.          * @param url
  13.          * @param clazz                解析的class字节码
  14.          * @param listener 请求成功监听器
  15.          * @param errorListener        请求失败监听器
  16.          */
  17.         public MyJsonRequest(String url, Class<T> clazz, Listener<T> listener,
  18.                         ErrorListener errorListener) {
  19.                 this(Method.GET, url, null, clazz, listener, errorListener);
  20.         }

  21.         /**
  22.          *
  23.          * @param method        请求方法 Use {@link com.android.volley.Request.Method}.
  24.          * @param url
  25.          * @param requestBody        如果是POST请求,可以提交form表单字符串,比如 name=zhangsan&age=20
  26.          * @param clazz                解析的class字节码
  27.          * @param listener 请求成功监听器
  28.          * @param errorListener        请求失败监听器
  29.          */
  30.         public MyJsonRequest(int method, String url, String requestBody, Class<T> clazz,
  31.                         Listener<T> listener, ErrorListener errorListener) {
  32.                 super(method, url, null, listener, errorListener);

  33.                 this.clazz = clazz;
  34.                 gson = new Gson();
  35.         }

  36.         @Override
  37.         protected Response<T> parseNetworkResponse(NetworkResponse response) {
  38.                 try {
  39.                         String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
  40.                         return Response.success(gson.fromJson(json, clazz),
  41.                                         HttpHeaderParser.parseCacheHeaders(response));
  42.                 } catch (UnsupportedEncodingException e) {
  43.                         return Response.error(new ParseError(e));
  44.                 } catch (JsonSyntaxException e) {
  45.                         return Response.error(new ParseError(e));
  46.                 }
  47.         }
  48. }
复制代码
  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.class, new Listener<NewsInfo>() {

  4.                 @Override
  5.                 public void onResponse(NewsInfo response) {
  6.                         System.out.println(response.getClass());
  7.                         System.out.println(response);
  8.                 }
  9.         }, null);
  10.         MyVolley.getRequestQueue().add(request);
  11. }
复制代码

(4).POST表单提交
  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.                 @Override
  5.                 public void onResponse(String response) {
  6.                         
  7.                 }
  8.         }, new ErrorListener() {

  9.                 @Override
  10.                 public void onErrorResponse(VolleyError error) {
  11.                         
  12.                 }
  13.         }){
  14.                 //覆写getBody()方法提交表单数据
  15.                 @Override
  16.                 public byte[] getBody() {
  17.                         return "name=zhangsan&age=15".getBytes();
  18.                 }
  19.         };
  20.         MyVolley.getRequestQueue().add(request);
  21. }
复制代码

(5).ImageLoader异步加载图片(防错位)
  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
  8. }

你可能感兴趣的:(Android_开源框架_Volley实例)