Volley完全解析

一、volley是什麼?

1、簡介

  Volley是Goole在2013年Google I/O大會上推出了一個新的網絡通信框架,它是開源的。從名字由來和配圖中無數急促的火箭可以看出 Volley 的特點:特別適合數據量小,通信頻繁的網絡操作。(個人認爲 Android 應用中絕大多數的網絡操作都屬於這種類型)。

  Volley加載圖片實現了兩級緩存(網絡緩存、文件緩存),沒有實現內存的緩存。Volley已經把各種異步任務、圖片採樣都封裝好了。內存緩存使用lrucache類實現,需要我們手動添加進去。沒有使用軟引用緩存。因爲4.0之後的android系統已經不推薦使用軟引用緩存了。

2、volley的總體設計

這裏寫圖片描述

這裏寫圖片描述

3、volley可以做什麼

JSON,圖像等的異步下載; 
處理get、post等網絡請求; 
網絡請求的排序(scheduling); 
網絡請求的優先級處理; 
緩存; 
多級別取消請求; 
和Activity和生命週期的聯動(Activity結束時同時取消所有網絡請求); 
等等。

二、圖片的三級緩存在volley中的實現

  其實volley可以完全取代我們手寫的三級緩存,因爲google已經對volley進行了非常好的封裝,具體說明如下:

1、volley的推薦用法-單例模式

  使用volley時,我們推薦把volley的使用封裝成單例使用。在application中初始化它。具體代碼如下:

單例:

package com.ht.xiangqu.util;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
/**
 * Created by annuo on 2015/6/16.
 */
public class RequestManager {
    private static RequestManager ourInstance;
    private RequestQueue requestQueue;
    private ImageLoader imageLoader;
    public static RequestManager createInstance(Context context) {
        if (context != null) {
            if (ourInstance == null) {
                ourInstance = new RequestManager(context);
            } else {
                throw new IllegalArgumentException("Context must be set");
            }
        }
        return ourInstance;
    }
    public static RequestManager getInstance() {
        return ourInstance;
    }
    private RequestManager(Context context) {
        requestQueue = Volley.newRequestQueue(context);
        imageLoader = new ImageLoader(
                requestQueue,
                new ImageLoader.ImageCache() {
                    private LruCache<String, Bitmap> cache
                            = new LruCache<>(20);
                    @Override
                    public Bitmap getBitmap(String url) {
                        return cache.get(url);
                    }
                    @Override
                    public void putBitmap(String url, Bitmap bitmap) {
                        cache.put(url, bitmap);
                    }
                }
        );
    }
    public RequestQueue getRequestQueue() {
        return requestQueue;
    }
    public ImageLoader getImageLoader() {
        return imageLoader;
    }
}

application:

package com.ht.xiangqu.util;
import android.app.Application;
import android.util.Log;
/** * Created by annuo on 2015/6/16.
*/
publicclassMainApplation extends Application {  
@OverridepublicvoidonCreate() {  
super.onCreate();  
RequestManager.createInstance(getApplicationContext());  
Log.d("nihao","nihao"); }
}

2、內存緩存

  只有加載圖片的時候纔會有內存緩存,對於字符串一般都是之後文件緩存。

  google並沒有自動的幫我們實現內存的緩存,需要我們自己手動加入進去。內存緩存在單例類中已經體現了(即LruCache),以後我們每次使用的時候都不必再加入內存緩存。LruCache這個類是Android3.1版本中提供的,如果你是在更早的Android版本中開發,則需要導入android-support-v4的jar包。

3、文件緩存

  volley已經默認幫我們實現了文件的緩存。我們通過源代碼看一下:

/**
     * Constructs a new ImageLoader.
     * @param queue The RequestQueue to use for making image requests.
     * @param imageCache The cache to use as an L1 cache.
     */
    public ImageLoader(RequestQueue queue, ImageCache imageCache) {
        mRequestQueue = queue;
        mCache = imageCache;
    }

  以上代碼是imageloader中的一段代碼,從中我們可以看到在構造imageloader時,我們已經默認的建立了一個L1級的緩存(文件緩存)。

那volley緩存下來的文件到底在哪呢?見下圖:

這裏寫圖片描述

  具體的位置就在如圖所示的位置。即data/data/應用程序的包名/volley,如果沒有修改volley的緩存位置,默認名字叫volley。

4、圖片的二次採樣的問題

  其實volley默認的已經幫我們做了圖片的二次採樣,只是需要我們在進行請求的時候,多加入兩個參數。我們一般都忽略了這個問題,最後導致的是不斷的OOM。

  /**
     * 這是訪問網絡圖片的核心方法
     * @param requestUrl
     * @param imageListener
     * @param maxWidth
     * @param maxHeight
     * @return
     */
    public ImageContainer get(String requestUrl, ImageListener imageListener,
            int maxWidth, int maxHeight) {
   <span style="white-space:pre">	</span>Request<?> newRequest =
            new ImageRequest(requestUrl, new Listener<Bitmap>() {
                @Override
                public void onResponse(Bitmap response) {
                    onGetImageSuccess(cacheKey, response);
                }
            }, maxWidth, maxHeight,
            Config.RGB_565, new ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    onGetImageError(cacheKey, error);
                }
            });

        mRequestQueue.add(newRequest);
        mInFlightRequests.put(cacheKey,
                new BatchedImageRequest(newRequest, imageContainer));
        return imageContainer;
    }

  以上代碼是imageloader的核心方法,其中有兩個參數是maxWidth,maxHeight,我們一般都忽略了這兩個參數。默認值是0和0,這樣二次採樣算法就不起作用了,我們得到的圖片是從服務器1:1哪來的。但是一般我們設置了這兩個參數,就可以得到我們希望的縮小比例的圖片。這樣就可以完全的避免OOM。

三、volley的其他問題

1、圓角圖片的問題

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) {
                    //在這裏可以設置,如果想得到圓角圖片的畫,可以對bitmap進行加工,可以給imageview加一個
                    //額外的參數
                    view.setImageBitmap(response.getBitmap());
                } else if (defaultImageResId != 0) {
                    view.setImageResource(defaultImageResId);
                }
            }
        };
    }

2、listview複用時,解決圖片錯位的問題

/**
     * 使用此方法能夠解決圖片錯亂問題
     * @param view
     * @param defaultImageResId
     * @param errorImageResId
     * @param url
     * @return
     */
    public static ImageListener getImageListener(
            final ImageView view,
            final int defaultImageResId,
            final int errorImageResId,
            final String url) {
        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) {
                    //在這裏可以設置,如果想得到圓角圖片的畫,可以對bitmap進行加工,可以給imageview加一個
                    //額外的參數
                    String urlTag = (String) view.getTag();
                    if(urlTag!=null && urlTag.trim().equals(url)){
                        view.setImageBitmap(response.getBitmap());
                    }
                } else if (defaultImageResId != 0) {
                    view.setImageResource(defaultImageResId);
                }
            }
        };
    }

四、volley的具體用法

  關於這塊內容,網絡上有很多的資料,總之volley使用起來非常的簡單,感興趣的可以去網絡上查找相關的資料進行學習。volley的加載速度絕對出乎你的意料。

——知道自己是誰,要什麼,能跳多高,而且敢跳,並承受跳了可能失敗的所有結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章