編寫:kesenhoo - 原文:http://developer.android.com/training/volley/requestqueue.html
前一節(jié)課演示了如何使用 Volley.newRequestQueue 這一簡便的方法來建立一個(gè)RequestQueue,這是利用了 Volley 默認(rèn)行為的優(yōu)勢。這節(jié)課會(huì)介紹如何顯式地建立一個(gè) RequestQueue,以便滿足我們自定義的需求。
這節(jié)課同樣會(huì)介紹一種推薦的實(shí)現(xiàn)方式:創(chuàng)建一個(gè)單例的 RequestQueue,這使得 RequestQueue 能夠持續(xù)保持在我們 app 的生命周期中。
一個(gè) RequestQueue 需要兩部分來支持它的工作:一部分是網(wǎng)絡(luò)操作,用來傳輸請求,另外一個(gè)是用來處理緩存操作的 Cache。在 Volley 的工具箱中包含了標(biāo)準(zhǔn)的實(shí)現(xiàn)方式:DiskBasedCache 提供了每個(gè)文件與對應(yīng)響應(yīng)數(shù)據(jù)一一映射的緩存實(shí)現(xiàn)。 BasicNetwork 提供了一個(gè)基于 AndroidHttpClient 或者 HttpURLConnection 的網(wǎng)絡(luò)傳輸。
BasicNetwork 是 Volley 默認(rèn)的網(wǎng)絡(luò)操作實(shí)現(xiàn)方式。一個(gè) BasicNetwork 必須使用我們的 app 用于連接網(wǎng)絡(luò)的 HTTP Client 進(jìn)行初始化。這個(gè) Client 通常是AndroidHttpClient 或者 HttpURLConnection:
我們可以通過檢查系統(tǒng)版本選擇合適的 HTTP Client,從而創(chuàng)建一個(gè)能夠運(yùn)行在所有 Android 版本上的應(yīng)用。例如:
HttpStack stack;
...
// If the device is running a version >= Gingerbread...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
// ...use HttpURLConnection for stack.
} else {
// ...use AndroidHttpClient for stack.
}
Network network = new BasicNetwork(stack);
下面的代碼片段演示了如何一步步建立一個(gè) RequestQueue:
RequestQueue mRequestQueue;
// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());
// Instantiate the RequestQueue with the cache and network.
mRequestQueue = new RequestQueue(cache, network);
// Start the queue
mRequestQueue.start();
String url ="http://www.myurl.com";
// Formulate the request and handle the response.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// Do something with the response
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// Handle error
}
});
// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);
...
如果我們僅僅是想做一個(gè)單次的請求并且不想要線程池一直保留,我們可以通過使用在前面一課:發(fā)送一個(gè)簡單的請求(Sending a Simple Request)文章中提到的 Volley.newRequestQueue() 方法,在任何需要的時(shí)刻創(chuàng)建 RequestQueue,然后在我們的響應(yīng)回調(diào)里面執(zhí)行 stop() 方法來停止操作。但是更通常的做法是創(chuàng)建一個(gè) RequestQueue 并設(shè)置為一個(gè)單例。下面部分將演示這種做法。
如果我們的應(yīng)用需要持續(xù)地使用網(wǎng)絡(luò),更加高效的方式應(yīng)該是建立一個(gè) RequestQueue 的單例,這樣它能夠持續(xù)保持在整個(gè) app 的生命周期中。我們可以通過多種方式來實(shí)現(xiàn)這個(gè)單例。推薦的方式是實(shí)現(xiàn)一個(gè)單例類,里面封裝了 RequestQueue 對象與其它的 Volley 功能。另外一個(gè)方法是繼承 Application 類,并在 Application.OnCreate() 方法里面建立 RequestQueue。但是我們并不推薦這個(gè)方法,因?yàn)橐粋€(gè) static 的單例能夠以一種更加模塊化的方式提供同樣的功能。
一個(gè)關(guān)鍵的概念是 RequestQueue 必須使用 Application context 來實(shí)例化,而不是 Activity context。這確保了 RequestQueue 在我們 app 的生命周期中一直存活,而不會(huì)因?yàn)?activity 的重新創(chuàng)建而被重新創(chuàng)建(例如,當(dāng)用戶旋轉(zhuǎn)設(shè)備時(shí))。
下面是一個(gè)單例類,提供了 RequestQueue 與 ImageLoader 功能:
public class MySingleton {
private static MySingleton mInstance;
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private static Context mCtx;
private MySingleton(Context context) {
mCtx = context;
mRequestQueue = getRequestQueue();
mImageLoader = new ImageLoader(mRequestQueue,
new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap>
cache = new LruCache<String, Bitmap>(20);
@Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url, bitmap);
}
});
}
public static synchronized MySingleton getInstance(Context context) {
if (mInstance == null) {
mInstance = new MySingleton(context);
}
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
// getApplicationContext() is key, it keeps you from leaking the
// Activity or BroadcastReceiver if someone passes one in.
mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
public ImageLoader getImageLoader() {
return mImageLoader;
}
}
下面演示了利用單例類來執(zhí)行 RequestQueue 的操作:
// Get a RequestQueue
RequestQueue queue = MySingleton.getInstance(this.getApplicationContext()).
getRequestQueue();
...
// Add a request (in this example, called stringRequest) to your RequestQueue.
MySingleton.getInstance(this).addToRequestQueue(stringRequest);