Volley簡介
Volley是Goole在2013年Google I/O大會上推出了一個新的網絡通信框架,它是開源的。從名字由來和配圖中無數急促的火箭可以看出 Volley 的特點:特別適合數據量小,通信頻繁的網絡操作。
Volley加載JsonObjectRequest數據、StringRequest數據、ImageRequest圖片數據僅僅實現了兩級緩存(網絡緩存、文件緩存),沒有實現內存的緩存。Volley已經把各種異步任務、圖片採樣都封裝好了。
內存緩存使用lrucache類實現,需要我們手動添加進去。沒有使用軟引用緩存。因爲4.0之後的android系統已經不推薦使用軟引用緩存了。
Volley請求數據原理圖
Volley緩存機制
volley發起一個請求先從緩存中去查找,如果緩存有數據,直接返回結果,如果沒有緩存中沒有數據,volley會發起網絡請求,此時展示數據,同時將網絡獲取的數據保存到緩存中。
那咱們看一下緩存數據在哪裏:想要使用Volley請求數據,必須要獲取RequestQueue這個對象,Volley提供了公共靜態的方法:newRequestQueue(Context context)
public static RequestQueue newRequestQueue(Context context) {
return newRequestQueue(context, null);
}
該方法中返回了:return newRequestQueue(context, null); 接續跟着代碼走
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
String userAgent = "volley/0";
try {
String packageName = context.getPackageName();
PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
userAgent = packageName + "/" + info.versionCode;
} catch (NameNotFoundException e) {
}
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork(stack);
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
return queue;
}
此時我們發現,緩存的地址: File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);也就是默認的緩存地址是程序安裝包下的data/data/中,接下來看一下RequestQueue的構造方法說明,繼續看源碼
/**
* Creates the worker pool. Processing will not begin until {@link #start()} is called.
*
* @param cache A Cache to use for persisting responses to disk
* @param network A Network interface for performing HTTP requests
*/
public RequestQueue(Cache cache, Network network) {
this(cache, network, DEFAULT_NETWORK_THREAD_POOL_SIZE);
}
從源碼註釋中cache A Cache to use for persisting responses to disk我們知道緩存其實是放到SD卡中了,並沒有實現內存緩存即並沒有實現LruCache
Volley內存緩存
只有加載圖片的時候纔會有內存緩存,對於字符串一般都是文件緩存。我們學習一下ImageLoader,內存緩存的實現
ImageLoader構造方法:
/**
* 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;
}
參數一是RequestQueue,其中可以指定文件緩存地址,我們通過單例模式創建RequestQueue這個類,就可以將文件緩存路徑指定到SD卡上
參數二是內存緩存,這個類是接口需要實現其中方法
/**
* Simple cache adapter interface. If provided to the ImageLoader, it
* will be used as an L1 cache before dispatch to Volley. Implementations
* must not block. Implementation with an LruCache is recommended.
*/
public interface ImageCache {
public Bitmap getBitmap(String url);
public void putBitmap(String url, Bitmap bitmap);
}
給大家一個實例代碼:
ImageLoader.ImageCache imageCache = new ImageLoader.ImageCache() {
// 內存緩存
int maxSize = (int) (Runtime.getRuntime().totalMemory()/8);
LruCache<String,Bitmap> mLruCache = new LruCache<String,Bitmap>(maxSize){
// 告訴LruCache存入的數據多大
@Override
protected int sizeOf(String key, Bitmap value) {
// 存入每張圖片的大小
return value.getRowBytes()*value.getHeight();
}
};
// 緩存中獲取數據
@Override
public Bitmap getBitmap(String url) {
return mLruCache.get(url);
}
// 第一次使用,肯定沒有數據,聯網請求,將數據存起來,方便以後使用
@Override
public void putBitmap(String url, Bitmap bitmap) {
mLruCache.put(url,bitmap);
}
};
對於請求圖片的ImageLoader,這個類請求圖片的機制是這樣的,就是一個經典的三級緩存了:
1、當ImageLoader發起圖片請求時,先從內存緩存LruCache中根據key(即請求url)獲取緩存數據,如果有數據,直接返回數據,不進行其他操作了
2、如果內存緩存中沒有數據,ImageLoader中第一參數requestQueue就會先從文件緩存中查找是否存在數據,如果有數據,直接返回數據,不進行聯網操作了
3、如果文件緩存中麼有數據,那就只能進行聯網操作,聯網操作獲取數據, Volley會根據這個請求是否設置緩存進行緩存與否,將數據返回