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. }
相關文章
相關標籤/搜索