ym—— Android網絡框架Volley(體驗篇)

VolleyGoogle I/O 2013推出的網絡通訊庫,在volley推出以前咱們通常會選擇比較成熟的第三方網絡通訊庫,如:android

他們各有優劣,以前我的則比較喜歡用android-async-http, 現在Google推出了官方的針對Android平臺上的網絡通訊庫,能使網絡通訊更快,更簡單,更健壯,Volley在提供了高性能網絡通信功能的同 時,對網絡圖片加載也提供了良好的支持,徹底能夠知足簡單REST客戶端的需求, 咱們沒有理由不跟上時代的潮流git

 

使用Volleygithub

 

下載Volley源碼並build jar包。json

$ git clone https://android.googlesource.com/platform/frameworks/volley緩存

$ cd volley服務器

$ android update project -p網絡

$ ant jar架構

而後把生成的jar包引用到咱們的項目中,extras目錄下則包含了目前最新的volley源碼。異步

 

說明async

此Demo主要介紹了平常網絡開發經常使用的基本功能,但volley的擴展性很強,能夠根據須要定製你本身的網絡請求。

volley視頻地址: http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded

 

以上是在Google IO的演講上ppt的配圖,從上面這張圖咱們能夠看出,volley適合快速,簡單的請求(Json對象,圖片加載)。

volley的特性:

 

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

 

接下來,咱們來學習簡單的使用下volley給我提供的API吧。

1.首先拿到一個請求隊列(RequestQueue只須要一個實例便可,不像AsyncTask每次使用都要new一個)

 

1. // 初始化RequestQueue一個activity只須要一個 
2. private void initRequestQueue() { 
3. mQueue = Volley.newRequestQueue(getApplicationContext()); 
4. }

2.實現volley的異步請求類(JsonObjectRequest,JsonArrayRequest,StringRequest,ImageRequest

 

因爲用法都相差不大,我就不一一舉例了,舉幾個經常使用有表明性的例子:

如下代碼是StringRequest的get請求:

01. private void loadGetStr(String url) { 
02.  
03. StringRequest srReq = new StringRequest(Request.Method.GET, url, 
04. new StrListener(), new StrErrListener()) { 
05.  
06. protected final String TYPE_UTF8_CHARSET = "charset=UTF-8"
07.  
08. // 重寫parseNetworkResponse方法改變返回頭參數解決亂碼問題 
09. // 主要是看服務器編碼,若是服務器編碼不是UTF-8的話那麼就須要本身轉換,反之則不須要 
10. @Override 
11. protected Response<String> parseNetworkResponse( 
12. NetworkResponse response) { 
13. try
14. String type = response.headers.get(HTTP.CONTENT_TYPE); 
15. if (type == null) { 
16. type = TYPE_UTF8_CHARSET; 
17. response.headers.put(HTTP.CONTENT_TYPE, type); 
18. } else if (!type.contains("UTF-8")) { 
19. type += ";" + TYPE_UTF8_CHARSET; 
20. response.headers.put(HTTP.CONTENT_TYPE, type); 
21.
22. } catch (Exception e) { 
23.
24. return super.parseNetworkResponse(response); 
25.
26. }; 
27. srReq.setShouldCache(true); // 控制是否緩存 
28. startVolley(srReq); 
29. }

 

如下代碼是JsonObjectRequest的post請求:

01. // post請求 
02. private void loadPostJson(String url) { 
03. // 第二個參數說明: 
04. // Constructor which defaults to GET if jsonRequest is null, POST 
05. // otherwise. 
06. // 默認狀況下設成null爲get方法,不然爲post方法。 
07. JsonObjectRequest srReq = new JsonObjectRequest(url, null
08. new JsonListener(), new StrErrListener()) { 
09.  
10. @Override 
11. protected Map<String, String> getParams() throws AuthFailureError { 
12. Map<String, String> map = new HashMap<String, String>(); 
13. map.put("w", "2459115"); 
14. map.put("u", "f"); 
15. return map; 
16.
17. }; 
18. srReq.setShouldCache(false); // 控制是否緩存 
19. startVolley(srReq); 
20. }

 

你們注意看的話,不管是JsonObjectReques的postt仍是StringRequest的get都須要傳入兩個監聽函數一個是成功一個是失敗,成功監聽他們會返回相應類型的數據:

01. // Str請求成功回調 
02. private class StrListener implements Listener<String> { 
03.  
04. @Override 
05. public void onResponse(String arg0) { 
06. Log.e(Tag, arg0); 
07.  
08.
09.  
10.
11.  
12. // Gson請求成功回調 
13. private class GsonListener implements Listener<ErrorRsp> { 
14.  
15. @Override 
16. public void onResponse(ErrorRsp arg0) { 
17. Toast.makeText(mContext, arg0.toString(), Toast.LENGTH_LONG).show(); 
18.
19.  
20.
21. // 共用失敗回調 
22. private class StrErrListener implements ErrorListener { 
23.  
24. @Override 
25. public void onErrorResponse(VolleyError arg0) { 
26. Toast.makeText(mContext, 
27. VolleyErrorHelper.getMessage(arg0, mContext), 
28. Toast.LENGTH_LONG).show(); 
29.
30.  
31. }

 

接下來是ImageRequest

01. /**
02. * 第三第四個參數分別用於指定容許圖片最大的寬度和高度,若是指定的網絡圖片的寬度或高度大於這裏的最大值,則會對圖片進行壓縮,
03. * 指定成0的話就表示無論圖片有多大,都不會進行壓縮。
04.
05. * @param url
06. *            圖片地址
07. * @param listener
08. * @param maxWidth
09. *            指定容許圖片最大的寬度
10. * @param maxHeight
11. *            指定容許圖片最大的高度
12. * @param decodeConfig
13. *            指定圖片的顏色屬性,Bitmap.Config下的幾個常量.
14. * @param errorListener
15. */ 
16. private void getImageRequest(final ImageView iv, String url) { 
17. ImageRequest imReq = new ImageRequest(url, new Listener<Bitmap>() { 
18.  
19. @Override 
20. public void onResponse(Bitmap arg0) { 
21. iv.setImageBitmap(arg0); 
22.
23. }, 60, 60, Bitmap.Config.ARGB_8888, new StrErrListener()); 
24. startVolley(imReq); 
25. }

 

看到如今你們確定會疑惑寫了這麼多不一樣類型的Request到底如何運行?接下請看:

01. // 添加及開始請求 
02. private void startVolley(Request req) { 
03.  
04. // 設置超時時間 
05. // req.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 1, 1.0f)); 
06. // 將請求加入隊列 
07. mQueue.add(req); 
08. // 開始發起請求 
09. mQueue.start(); 
10. }

 

volley不只提供了這些請求的方式,還提供了加載圖片的一些方法和控件:

好比咱們一個列表須要加載不少圖片咱們可使用volley給咱們提供的ImageLoader( ImageLoader比ImageRequest更加高效,由於它不只對圖片進行緩存,還能夠過濾掉重複的連接,避免重複發送請求。)

01. public class ImageAdapter extends ArrayAdapter<String> { 
02.  
03. private RequestQueue mQueue; 
04. private ImageLoader mImageLoader; 
05.  
06. public ImageAdapter(Context context, List<String> objects) { 
07. super(context, 0, objects); 
08. mQueue = Volley.newRequestQueue(getContext()); 
09. mImageLoader = new ImageLoader(mQueue, new BitmapCache()); 
10.
11.  
12. @Override 
13. public View getView(int position, View convertView, ViewGroup parent) { 
14. String url = getItem(position); 
15. ImageView imageView; 
16. if (convertView == null) { 
17. imageView = new ImageView(getContext()); 
18. } else
19. imageView = (ImageView) convertView; 
20.
21. // getImageListener(imageView控件對象,默認圖片地址,失敗圖片地址); 
22. ImageListener listener = ImageLoader.getImageListener(imageView, android.R.drawable.ic_menu_rotate, android.R.drawable.ic_delete); 
23. // get(圖片地址,listener,寬,高);自動幫你處理圖片的寬高不再怕大圖片的oom了 
24. mImageLoader.get(url, listener,100,200); 
25. return imageView; 
26.
27.  
28. }

 

固然還須要重寫ImageCache這個類 //使用LruCache不再用怕加載多張圖片oom了

01. public class <span style="font-family: Arial;">BitmapCache</span><span style="font-family: Arial;"> extends LruCache<String, Bitmap> implements ImageCache {</span> 
02. // LruCache 原理:Cache保存一個強引用來限制內容數量,每當Item被訪問的時候,此Item就會移動到隊列的頭部。 當cache已滿的時候加入新的item時,在隊列尾部的item會被回收。 
03. // 解釋:當超出指定內存值則移除最近最少用的圖片內存 
04. public static int getDefaultLruCacheSize() { 
05. // 拿到最大內存 
06. final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); 
07. // 拿到內存的八分之一來作圖片內存緩存 
08. final int cacheSize = maxMemory / 8
09.  
10. return cacheSize; 
11.
12.  
13. public BitmapLruCache() { 
14. this(getDefaultLruCacheSize()); 
15.
16.  
17. public BitmapLruCache(int sizeInKiloBytes) { 
18. super(sizeInKiloBytes); 
19.
20.  
21. @Override 
22. protected int sizeOf(String key, Bitmap value) { 
23. return value.getRowBytes() * value.getHeight() / 1024
24.
25.  
26. @Override 
27. public Bitmap getBitmap(String url) { 
28. return get(url); 
29.
30.  
31. @Override 
32. public void putBitmap(String url, Bitmap bitmap) { 
33. put(url, bitmap); 
34.
35. }

 

 

Volley還提供的加載圖片的控件com.android.volley.NetworkImageView。 (這個控件在被從父控件detach的時候,會自動取消網絡請求的,即徹底不用咱們擔憂相關網絡請求的生命週期問題,並且 NetworkImageView還會根據你對圖片設置的width和heigh自動壓縮該圖片不會產生多的內存,還有NetworkImageView 在列表中使用不會圖片錯誤)

1. <com.android.volley.toolbox.NetworkImageView 
2. android:id="@+id/network_image_view" 
3. android:layout_width="100dp" 
4. android:layout_height="100dp" />

 

使用方法:

1. private void networkImageViewUse(NetworkImageView iv, String url) { 
2. ImageLoader imLoader = new ImageLoader(mQueue, new BitmapLruCache()); 
3. iv.setDefaultImageResId(R.drawable.ic_launcher); 
4. iv.setErrorImageResId(R.drawable.ic_launcher); 
5. iv.setImageUrl(url, imLoader); 
6. }

 

咱們說了這麼多都是請求,那麼如何取消請求呢?

 

1.activity自動銷燬時它會自定取消全部請求。

2.給請求設置標籤

request.setTag("My Tag");  

取消全部指定標記的請求:

 

request.cancelAll("My Tag");    

Volley的架構設計:

 

其中藍色部分表明主線程,綠色部分表明緩存線程,橙色部分表明網絡線程。咱們在主線程中 調用RequestQueue的add()方法來添加一條網絡請求,這條請求會先被加入到緩存隊列當中,若是發現能夠找到相應的緩存結果就直接讀取緩存並 解析,而後回調給主線程。若是在緩存中沒有找到結果,則將這條請求加入到網絡請求隊列中,而後處理髮送HTTP請求,解析響應結果,寫入緩存,並回調主線 程。Google I/O 2013推出的網絡通訊庫,在volley推出以前咱們通常會選擇比較成熟的第三方網絡通訊庫,如:

他們各有優劣,以前我的則比較喜歡用android-async-http, 現在Google推出了官方的針對Android平臺上的網絡通訊庫,能使網絡通訊更快,更簡單,更健壯,Volley在提供了高性能網絡通信功能的同 時,對網絡圖片加載也提供了良好的支持,徹底能夠知足簡單REST客戶端的需求, 咱們沒有理由不跟上時代的潮流

 

使用Volley

 

下載Volley源碼並build jar包。

$ git clone https://android.googlesource.com/platform/frameworks/volley

$ cd volley

$ android update project -p

$ ant jar

而後把生成的jar包引用到咱們的項目中,extras目錄下則包含了目前最新的volley源碼。

 

說明

此Demo主要介紹了平常網絡開發經常使用的基本功能,但volley的擴展性很強,能夠根據須要定製你本身的網絡請求。

volley視頻地址: http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded

 

以上是在Google IO的演講上ppt的配圖,從上面這張圖咱們能夠看出,volley適合快速,簡單的請求(Json對象,圖片加載)。

volley的特性:

 

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

 

接下來,咱們來學習簡單的使用下volley給我提供的API吧。

1.首先拿到一個請求隊列(RequestQueue只須要一個實例便可,不像AsyncTask每次使用都要new一個)

 

1. // 初始化RequestQueue一個activity只須要一個 
2. private void initRequestQueue() { 
3. mQueue = Volley.newRequestQueue(getApplicationContext()); 
4. }

2.實現volley的異步請求類(JsonObjectRequest,JsonArrayRequest,StringRequest,ImageRequest

 

因爲用法都相差不大,我就不一一舉例了,舉幾個經常使用有表明性的例子:

如下代碼是StringRequest的get請求:

01. private void loadGetStr(String url) { 
02.  
03. StringRequest srReq = new StringRequest(Request.Method.GET, url, 
04. new StrListener(), new StrErrListener()) { 
05.  
06. protected final String TYPE_UTF8_CHARSET = "charset=UTF-8"
07.  
08. // 重寫parseNetworkResponse方法改變返回頭參數解決亂碼問題 
09. // 主要是看服務器編碼,若是服務器編碼不是UTF-8的話那麼就須要本身轉換,反之則不須要 
10. @Override 
11. protected Response<String> parseNetworkResponse( 
12. NetworkResponse response) { 
13. try
14. String type = response.headers.get(HTTP.CONTENT_TYPE); 
15. if (type == null) { 
16. type = TYPE_UTF8_CHARSET; 
17. response.headers.put(HTTP.CONTENT_TYPE, type); 
18. } else if (!type.contains("UTF-8")) { 
19. type += ";" + TYPE_UTF8_CHARSET; 
20. response.headers.put(HTTP.CONTENT_TYPE, type); 
21.
22. } catch (Exception e) { 
23.
24. return super.parseNetworkResponse(response); 
25.
26. }; 
27. srReq.setShouldCache(true); // 控制是否緩存 
28. startVolley(srReq); 
29. }

 

如下代碼是JsonObjectRequest的post請求:

01. // post請求 
02. private void loadPostJson(String url) { 
03. // 第二個參數說明: 
04. // Constructor which defaults to GET if jsonRequest is null, POST 
05. // otherwise. 
06. // 默認狀況下設成null爲get方法,不然爲post方法。 
07. JsonObjectRequest srReq = new JsonObjectRequest(url, null
08. new JsonListener(), new StrErrListener()) { 
09.  
10. @Override 
11. protected Map<String, String> getParams() throws AuthFailureError { 
12. Map<String, String> map = new HashMap<String, String>(); 
13. map.put("w", "2459115"); 
14. map.put("u", "f"); 
15. return map; 
16.
17. }; 
18. srReq.setShouldCache(false); // 控制是否緩存 
19. startVolley(srReq); 
20. }

 

你們注意看的話,不管是JsonObjectReques的postt仍是StringRequest的get都須要傳入兩個監聽函數一個是成功一個是失敗,成功監聽他們會返回相應類型的數據:

01. // Str請求成功回調 
02. private class StrListener implements Listener<String> { 
03.  
04. @Override 
05. public void onResponse(String arg0) { 
06. Log.e(Tag, arg0); 
07.  
08.
09.  
10.
11.  
12. // Gson請求成功回調 
13. private class GsonListener implements Listener<ErrorRsp> { 
14.  
15. @Override 
16. public void onResponse(ErrorRsp arg0) { 
17. Toast.makeText(mContext, arg0.toString(), Toast.LENGTH_LONG).show(); 
18.
19.  
20.
21. // 共用失敗回調 
22. private class StrErrListener implements ErrorListener { 
23.  
24. @Override 
25. public void onErrorResponse(VolleyError arg0) { 
26. Toast.makeText(mContext, 
27. VolleyErrorHelper.getMessage(arg0, mContext), 
28. Toast.LENGTH_LONG).show(); 
29.
30.  
31. }

 

接下來是ImageRequest

01. /**
02. * 第三第四個參數分別用於指定容許圖片最大的寬度和高度,若是指定的網絡圖片的寬度或高度大於這裏的最大值,則會對圖片進行壓縮,
03. * 指定成0的話就表示無論圖片有多大,都不會進行壓縮。
04.
05. * @param url
06. *            圖片地址
07. * @param listener
08. * @param maxWidth
09. *            指定容許圖片最大的寬度
10. * @param maxHeight
11. *            指定容許圖片最大的高度
12. * @param decodeConfig
13. *            指定圖片的顏色屬性,Bitmap.Config下的幾個常量.
14. * @param errorListener
15. */ 
16. private void getImageRequest(final ImageView iv, String url) { 
17. ImageRequest imReq = new ImageRequest(url, new Listener<Bitmap>() { 
18.  
19. @Override 
20. public void onResponse(Bitmap arg0) { 
21. iv.setImageBitmap(arg0); 
22.
23. }, 60, 60, Bitmap.Config.ARGB_8888, new StrErrListener()); 
24. startVolley(imReq); 
25. }

 

看到如今你們確定會疑惑寫了這麼多不一樣類型的Request到底如何運行?接下請看:

01. // 添加及開始請求 
02. private void startVolley(Request req) { 
03.  
04. // 設置超時時間 
05. // req.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 1, 1.0f)); 
06. // 將請求加入隊列 
07. mQueue.add(req); 
08. // 開始發起請求 
09. mQueue.start(); 
10. }

 

volley不只提供了這些請求的方式,還提供了加載圖片的一些方法和控件:

好比咱們一個列表須要加載不少圖片咱們可使用volley給咱們提供的ImageLoader( ImageLoader比ImageRequest更加高效,由於它不只對圖片進行緩存,還能夠過濾掉重複的連接,避免重複發送請求。)

01. public class ImageAdapter extends ArrayAdapter<String> { 
02.  
03. private RequestQueue mQueue; 
04. private ImageLoader mImageLoader; 
05.  
06. public ImageAdapter(Context context, List<String> objects) { 
07. super(context, 0, objects); 
08. mQueue = Volley.newRequestQueue(getContext()); 
09. mImageLoader = new ImageLoader(mQueue, new BitmapCache()); 
10.
11.  
12. @Override 
13. public View getView(int position, View convertView, ViewGroup parent) { 
14. String url = getItem(position); 
15. ImageView imageView; 
16. if (convertView == null) { 
17. imageView = new ImageView(getContext()); 
18. } else
19. imageView = (ImageView) convertView; 
20.
21. // getImageListener(imageView控件對象,默認圖片地址,失敗圖片地址); 
22. ImageListener listener = ImageLoader.getImageListener(imageView, android.R.drawable.ic_menu_rotate, android.R.drawable.ic_delete); 
23. // get(圖片地址,listener,寬,高);自動幫你處理圖片的寬高不再怕大圖片的oom了 
24. mImageLoader.get(url, listener,100,200); 
25. return imageView; 
26.
27.  
28. }

 

固然還須要重寫ImageCache這個類 //使用LruCache不再用怕加載多張圖片oom了

01. public class <span style="font-family: Arial;">BitmapCache</span><span style="font-family: Arial;"> extends LruCache<String, Bitmap> implements ImageCache {</span> 
02. // LruCache 原理:Cache保存一個強引用來限制內容數量,每當Item被訪問的時候,此Item就會移動到隊列的頭部。 當cache已滿的時候加入新的item時,在隊列尾部的item會被回收。 
03. // 解釋:當超出指定內存值則移除最近最少用的圖片內存 
04. public static int getDefaultLruCacheSize() { 
05. // 拿到最大內存 
06. final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); 
07. // 拿到內存的八分之一來作圖片內存緩存 
08. final int cacheSize = maxMemory / 8
09.  
10. return cacheSize; 
11.
12.  
13. public BitmapLruCache() { 
14. this(getDefaultLruCacheSize()); 
15.
16.  
17. public BitmapLruCache(int sizeInKiloBytes) { 
18. super(sizeInKiloBytes); 
19.
20.  
21. @Override 
22. protected int sizeOf(String key, Bitmap value) { 
23. return value.getRowBytes() * value.getHeight() / 1024
24.
25.  
26. @Override 
27. public Bitmap getBitmap(String url) { 
28. return get(url); 
29.
30.  
31. @Override 
32. public void putBitmap(String url, Bitmap bitmap) { 
33. put(url, bitmap); 
34.
35. }

 

 

Volley還提供的加載圖片的控件com.android.volley.NetworkImageView。 (這個控件在被從父控件detach的時候,會自動取消網絡請求的,即徹底不用咱們擔憂相關網絡請求的生命週期問題,並且 NetworkImageView還會根據你對圖片設置的width和heigh自動壓縮該圖片不會產生多的內存,還有NetworkImageView 在列表中使用不會圖片錯誤)

1. <com.android.volley.toolbox.NetworkImageView 
2. android:id="@+id/network_image_view" 
3. android:layout_width="100dp" 
4. android:layout_height="100dp" />

 

使用方法:

1. private void networkImageViewUse(NetworkImageView iv, String url) { 
2. ImageLoader imLoader = new ImageLoader(mQueue, new BitmapLruCache()); 
3. iv.setDefaultImageResId(R.drawable.ic_launcher); 
4. iv.setErrorImageResId(R.drawable.ic_launcher); 
5. iv.setImageUrl(url, imLoader); 
6. }

 

咱們說了這麼多都是請求,那麼如何取消請求呢?

 

1.activity自動銷燬時它會自定取消全部請求。

2.給請求設置標籤

request.setTag("My Tag");  

取消全部指定標記的請求:

 

request.cancelAll("My Tag");    

Volley的架構設計:

 

其中藍色部分表明主線程,綠色部分表明緩存線程,橙色部分表明網絡線程。咱們在主線程中 調用RequestQueue的add()方法來添加一條網絡請求,這條請求會先被加入到緩存隊列當中,若是發現能夠找到相應的緩存結果就直接讀取緩存並 解析,而後回調給主線程。若是在緩存中沒有找到結果,則將這條請求加入到網絡請求隊列中,而後處理髮送HTTP請求,解析響應結果,寫入緩存,並回調主線 程。

相關文章
相關標籤/搜索