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_圖片的三級緩存一文)相關知識
- https://android.googlesource.com/platform/frameworks/volley
複製代碼
(1).封裝MyVolley類
在使用Volley以前,應該先進行初始化(能夠自定義Application或者在SplashActivity中完成初始化),僅對外提供RequestQueue(添加request)和ImageLoader(下載圖片)get方法!
- /**
- * MyVolley.java
- * @author zimo2013
- * [url=home.php?mod=space&uid=189949]@See[/url] http://blog.csdn.net/zimo2013
- *
- */
- public class MyVolley {
- private static final String TAG = "MyVolley";
-
- private static MyVolley instance;
- private static RequestQueue mRequestQueue;
- private static ImageLoader mImageLoader;
- private final static int RATE = 8; // 默認分配最大空間的幾分之一
-
- private MyVolley(Context context) {
- mRequestQueue = Volley.newRequestQueue(context);
-
- // 肯定在LruCache中,分配緩存空間大小,默認程序分配最大空間的 1/8
- ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- int maxSize = manager.getMemoryClass() / RATE; // 好比 64M/8,單位爲M
-
- //BitmapLruCache自定義緩存class,該框架自己支持二級緩存,在BitmapLruCache封裝一個軟引用緩存
- mImageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache(1024*1024*maxSize));
-
- LogUtil.i(TAG, "MyVolley初始化完成");
- }
-
- /**
- * 初始化Volley相關對象,在使用Volley前應該完成初始化
- *
- * @param context
- */
- public static void init(Context context) {
- if (instance == null) {
- instance = new MyVolley(context);
- } else {
- LogUtil.w(TAG, "已經初始化過,不須要再次調用init()");
- }
- }
-
- /**
- * 獲得請求隊列對象
- *
- * @return
- */
- public static RequestQueue getRequestQueue() {
- throwIfNotInit();
- return mRequestQueue;
- }
-
- /**
- * 獲得ImageLoader對象
- *
- * @return
- */
- public static ImageLoader getImageLoader() {
- throwIfNotInit();
- return mImageLoader;
- }
-
- /**
- * 檢查是否完成初始化
- */
- private static void throwIfNotInit() {
- if (instance == null) {// 還沒有初始化
- throw new IllegalStateException("MyVolley還沒有初始化,在使用前應該執行init()");
- }
- }
- }
複製代碼
(2).圖片的三級緩存相關類
- /**
- * LruCache緩存管理類,該類實現了ImageCache接口,並實現了LruCache
- * 一旦bitmap對象從LruCache中被擠出,將會被放置在BitmapSoftRefCache中,再配合該框架自己支持的硬盤緩存,能夠完成圖片三級緩存
- *
- * BitmapLruCache.java
- * @author zimo2013
- * @see http://blog.csdn.net/zimo2013
- *
- */
- public class BitmapLruCache extends LruCache<String, Bitmap> implements ImageCache {
- private static final String TAG = "BitmapLruCache";
-
- private BitmapSoftRefCache softRefCache;
-
- public BitmapLruCache(int maxSize) {
- super(maxSize);
- softRefCache = new BitmapSoftRefCache();
- }
-
- @Override
- protected int sizeOf(String key, Bitmap value) {
- return value.getRowBytes() * value.getHeight();
- }
-
- @Override
- protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
- if (evicted) {
- LogUtil.i(TAG, "空間已滿,緩存圖片被擠出:" + key);
- // 將被擠出的bitmap對象,添加至軟引用BitmapSoftRefCache
- softRefCache.putBitmap(key, oldValue);
- }
- }
-
- /**
- * 獲得緩存對象
- */
- @Override
- public Bitmap getBitmap(String url) {
- Bitmap bitmap = get(url);
- // 若是bitmap爲null,嘗試從軟引用緩存中查找
- if (bitmap == null) {
- bitmap = softRefCache.getBitmap(url);
- } else {
- LogUtil.i(TAG, "LruCache命中:" + url);
- }
- return bitmap;
- }
-
- /**
- * 添加緩存對象
- */
- @Override
- public void putBitmap(String url, Bitmap bitmap) {
- put(url, bitmap);
- }
-
- }
複製代碼
- /**
- * 軟引用緩存管理類
- *
- * BitmapSoftRefCache.java
- * @author zimo2013
- * @see http://blog.csdn.net/zimo2013
- *
- */
- public class BitmapSoftRefCache implements ImageCache{
- private static final String TAG = "BitmapSoftRefCache";
-
- private LinkedHashMap<String, SoftReference<Bitmap>> map;
- public BitmapSoftRefCache() {
- map = new LinkedHashMap<String, SoftReference<Bitmap>>();
- }
-
- /**
- * 從軟引用集合中獲得Bitmap對象
- */
- @Override
- public Bitmap getBitmap(String url) {
- Bitmap bitmap = null;
- SoftReference<Bitmap> softRef = map.get(url);
- if(softRef != null){
- bitmap = softRef.get();
- if(bitmap == null){
- map.remove(url); //從map中移除
- LogUtil.w(TAG, url+"對象已經被GC回收");
- }else{
- LogUtil.i(TAG, "命中"+url);
- }
- }
- return bitmap;
- }
-
- /**
- * 從軟引用集合中添加bitmap對象
- */
- @Override
- public void putBitmap(String url, Bitmap bitmap) {
- SoftReference<Bitmap> softRef = new SoftReference<Bitmap>(bitmap);
- map.put(url, softRef);
- }
-
- }
複製代碼
(3).圖片錯位
關於使用該框架形成圖片錯位問題,App使用了ImageLoader下載圖片,當ListView滾動很快時,仍是會發生錯位!記得聽別人提起過,使用該框架能夠避免圖片錯位,可是結果仍是會發生錯位,查看源碼並無找到相關避免錯位的措施,不知道是否是本身的使用方法不對,如您知曉,麻煩告知博主一下~這裏經過覆寫ImageListener方法,經過ImageView爲其指定Tag標籤,防止圖片錯位,即比對
下載完圖片的ImageUrl和當前該
ImageView的Tag是否相等~
- public class ImageListenerFactory{
-
- public static ImageListener getImageListener(final ImageView view,
- final int defaultImageResId, final int errorImageResId) {
- return new ImageListener() {
- @Override
- public void onErrorResponse(VolleyError error) {
- if (errorImageResId != 0) {
- view.setImageResource(errorImageResId);
- }
- }
-
- @Override
- public void onResponse(ImageContainer response, boolean isImmediate) {
- if (response.getBitmap() != null) {
-
- if(view.getTag().toString() == response.getRequestUrl()){
- view.setImageBitmap(response.getBitmap());
- }else{
- LogUtil.i(TAG, "圖片錯位");
- }
- } else if (defaultImageResId != 0) {
- view.setImageResource(defaultImageResId);
- }
- }
- };
- }
- }
複製代碼
2.網絡請求Request
(1).StringRequest
- public void testStringRequest(){
- String url = "http://www.baidu.com";
- //若是出現亂碼,應該修改StringRequest的parseNetworkResponse()方法,指定byte[]-->String 編碼
- MyVolley.getRequestQueue().add(new StringRequest(url, new Response.Listener<String>() {
-
- @Override
- public void onResponse(String response) {
- System.out.println("response:"+response);
- }
- }, new Response.ErrorListener() {
-
- @Override
- public void onErrorResponse(VolleyError error) {
-
- }
- }));
- }
複製代碼
(2).JsonObjectRequest
- public void testJsonObjectRequest(){
- String url = "http://api.mobile.meituan.com/group/v1/deal/new-cate-list/android/4.1?cityId=1";
- //若是出現亂碼,應該修改StringRequest的parseNetworkResponse()方法,指定byte[]-->String 編碼
- MyVolley.getRequestQueue().add(
- new JsonObjectRequest(url,
- null,
- new Response.Listener<JSONObject>() {
-
- @Override
- public void onResponse(JSONObject response) {
- //該JSONObject爲android系統提供的,若是但願獲得一個已經解析完的對象,能夠繼承JsonRequest
-
- //根據response,解析數據
- try {
- System.out.println(response.get("stid"));
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
- },new Response.ErrorListener() {
-
- @Override
- public void onErrorResponse(VolleyError error) {
- System.out.println(error);
- }
- })
- );
- }
複製代碼
(3).自定義Request(Json解析)
- /**
- * MyJsonRequest.java
- *
- * @author zimo2013
- * @see http://blog.csdn.net/zimo2013
- */
- public class MyJsonRequest<T> extends JsonRequest<T> {
- private Gson gson;
- private Class<T> clazz;
-
- /**
- * 默認爲GET請求方式
- * @param url
- * @param clazz 解析的class字節碼
- * @param listener 請求成功監聽器
- * @param errorListener 請求失敗監聽器
- */
- public MyJsonRequest(String url, Class<T> clazz, Listener<T> listener,
- ErrorListener errorListener) {
- this(Method.GET, url, null, clazz, listener, errorListener);
- }
-
- /**
- *
- * @param method 請求方法 Use {@link com.android.volley.Request.Method}.
- * @param url
- * @param requestBody 若是是POST請求,能夠提交form表單字符串,好比 name=zhangsan&age=20
- * @param clazz 解析的class字節碼
- * @param listener 請求成功監聽器
- * @param errorListener 請求失敗監聽器
- */
- public MyJsonRequest(int method, String url, String requestBody, Class<T> clazz,
- Listener<T> listener, ErrorListener errorListener) {
- super(method, url, null, listener, errorListener);
-
- this.clazz = clazz;
- gson = new Gson();
- }
-
- @Override
- protected Response<T> parseNetworkResponse(NetworkResponse response) {
- try {
- String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
- return Response.success(gson.fromJson(json, clazz),
- HttpHeaderParser.parseCacheHeaders(response));
- } catch (UnsupportedEncodingException e) {
- return Response.error(new ParseError(e));
- } catch (JsonSyntaxException e) {
- return Response.error(new ParseError(e));
- }
- }
- }
複製代碼
- public void testCustomRequest(){
- String urlString = "http://192.168.117.120:8080/news/json.html";
- MyJsonRequest<NewsInfo> request = new MyJsonRequest<NewsInfo>(urlString, NewsInfo.class, new Listener<NewsInfo>() {
-
- @Override
- public void onResponse(NewsInfo response) {
- System.out.println(response.getClass());
- System.out.println(response);
- }
- }, null);
- MyVolley.getRequestQueue().add(request);
- }
複製代碼
(4).POST表單提交
- public void testRequestByPost(){
- String urlString = "http://192.168.43.240:8080/news/servlet/Post";
- StringRequest request = new StringRequest(Method.POST, urlString, new Listener<String>() {
-
- @Override
- public void onResponse(String response) {
-
- }
- }, new ErrorListener() {
-
- @Override
- public void onErrorResponse(VolleyError error) {
-
- }
- }){
- //覆寫getBody()方法提交表單數據
- @Override
- public byte[] getBody() {
- return "name=zhangsan&age=15".getBytes();
- }
- };
- MyVolley.getRequestQueue().add(request);
- }
複製代碼
(5).ImageLoader異步加載圖片(防錯位)
- public void testImageLoader(){
- MyVolley.getImageLoader().get(imgUrl,
- //ImageListenerFactory爲自定義類,封裝後便可獲取圖片資源,完成UI更新
- ImageListenerFactory.getImageListener(//參考ImageLoader.getImageListener()
- imageView, // ImageView對象
- R.drawable.ic_launcher, // 默認Image,若是不設應置爲0
- R.drawable.ic_launcher)); // 錯誤Image,若是不設應置爲0
- }
|