Volley框架的使用(加載網絡圖片,加載json數據)

  1.Volley 簡介 
    1.  下載地址:https://android.googlesource.com/platform/frameworks/volley 
    2.   volley視頻:http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded
    3.   它是谷歌在2013年I/O大會上提出來的一套解決 Android與服務器端進行通信的框架
    4.   以前我們安卓端與服務器進行通信的時候一般都是使用 AsyncTask, HttpUrlConnection, HttpClient
        
2.功能介紹

  1.  json,圖片等異步下載
  2.  多級別取消請求
  3.  和Activity的生命週期的聯動(Activity結束,同時取消所有網絡請求)
  4.  網絡排序請求
  5.  網絡請求優先級處理
  6.  緩存

3. volley的使用

  3.1從服務器獲取數據

java 代碼


總結
Volley提供了JsonObjectRequest、JsonArrayRequest、StringRequest等Request形式。

  1. JsonObjectRequest:返回JSON對象。
  2. JsonArrayRequest:返回JsonArray。
  3. StringRequest:返回String,這樣可以自己處理數據,更加靈活。
  4. 另外可以繼承Request<T>自定義Request。

3.2 圖片加載

  1. 使用imageRequst下載圖片
  2. 使用imageload下載圖片
  3. 使用NetWorkImageView

4.框架詳解

流程:Volley.newRequestQueue(),初始化網絡請求隊列,然後add()消息到RequestQueue,NetworkDispatcher分發消息到NetWork調用HttpStack請求網絡,提交本地緩存信息到請求頭,NetWork封裝HttpStack返回數據,判斷是否使用緩存,或者拋出相關的異常。



相關注釋
  1. Volley 是一個幫助類 主要負責創建請求隊列 並且啓動隊列消息的循環
  2. HttpStack負責網絡解析請求 ,performRequest 返回的是一個Apache的HttpResponse
  3. 注:在2.3之前的版本,建議使用apache的HttpClient來處理網絡請求,在2.3之後的版本建議使用HttpUrlConnection
  4. NetWork 封裝了HttpStack的網絡請求,performRequest方法直接返回一個NetWorkResponse 處理了請求異常拋出VolleyError;
  5. NetWorkDispatcher 網絡調度(線程池),分發網絡請求到NetWork

———————————部分核心代碼--------------------------------------

1.RequestQueue.start() 啓動緩存調度和網絡調度

    public void start() {
        stop();  // Make sure any currently running dispatchers are stopped.
        // Create the cache dispatcher and start it.
        mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
        mCacheDispatcher.start();

        // Create network dispatchers (and corresponding threads) up to the pool size.
        for (int i = 0; i < mDispatchers.length; i++) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
                    mCache, mDelivery);
            mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }
    }
</pre><pre name="code" class="java" style="font-size: 14px;"><pre name="code" class="java">1.BaseNetWork   
網絡連接任務,@Override    
public NetworkResponse performRequest(Request<?> request) throws VolleyError { 
       long requestStart = SystemClock.elapsedRealtime();       
	   while (true) {           
	   HttpResponse httpResponse = null;           
	   byte[] responseContents = null;            
	   Map<String, String> responseHeaders = new HashMap<String, String>();           
	   try {                // Gather headers.                
	   Map<String, String> headers = new HashMap<String, String>();//請求頭信息。               
	   addCacheHeaders(headers, request.getCacheEntry());//添加本地緩存頭信息               
	   httpResponse = mHttpStack.performRequest(request, headers);//發出網絡請求               
	   StatusLine statusLine = httpResponse.getStatusLine();               
	   int statusCode = statusLine.getStatusCode();//HTTP狀態碼
                responseHeaders = convertHeaders(httpResponse.getAllHeaders());//解析頭信息 
				// Handle cache validation.               
				if (statusCode == HttpStatus.SC_NOT_MODIFIED) {//可以使用緩存數據         
				return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,          
				request.getCacheEntry().data, responseHeaders, true);     
				}
                // Some responses such as 204s do not have content.  We must check.    
				if (httpResponse.getEntity() != null) {//將返回數據 轉化爲byte數據   
				responseContents = entityToBytes(httpResponse.getEntity());        
        } else {//如果沒有返回內容。                 
		// Add 0 byte response as a way of honestly representing a                  
		// no-content request.                 
		responseContents = new byte[0];             
		}
                // if the request is slow, log it.    
				long requestLifetime = SystemClock.elapsedRealtime() - requestStart;      
				//如果請求時間過長 則打印Log               
				logSlowRequests(requestLifetime, request, responseContents, statusLine);
				
                if (statusCode < 200 || statusCode > 299) {//服務器返回異常 則拋出IOException   
				throw new IOException();                
				}                
				return new NetworkResponse(statusCode, responseContents, responseHeaders, false);        
				} catch (SocketTimeoutException e) {//鏈接超時 嘗試重新鏈接 如果達到嘗試次數 則會拋出VolleyError異常,此次請求則結束。    
				attemptRetryOnException("socket", request, new TimeoutError());         
				} catch (ConnectTimeoutException e) {//鏈接超時 嘗試重新鏈接 如果達到嘗試次數 則會拋出VolleyError異常,此次請求則結束。       
				attemptRetryOnException("connection", request, new TimeoutError());         
				} catch (MalformedURLException e) {//Bad URL              
				throw new RuntimeException("Bad URL " + request.getUrl(), e);    
				} catch (IOException e) {           
				int statusCode = 0;                
				NetworkResponse networkResponse = null;           
				if (httpResponse != null) {                  
				statusCode = httpResponse.getStatusLine().getStatusCode();       
				} else {//{//如果沒有返回httpResponse,就說明沒連接            
				throw new NoConnectionError(e);              
				}              
				VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());              
				if (responseContents != null) {                  
				networkResponse = new NetworkResponse(statusCode, responseContents,responseHeaders, false);              
				if (statusCode == HttpStatus.SC_UNAUTHORIZED ||                          
				statusCode == HttpStatus.SC_FORBIDDEN) {//認證失敗異常,重試             
				attemptRetryOnException("auth",request, new AuthFailureError(networkResponse)); 
				} else {//服務器異常                        // TODO: Only throw ServerError for 5xx status codes.                 
				throw new ServerError(networkResponse);                   
				}             
				} else {//網絡異常         
				throw new NetworkError(networkResponse);         
				}          
				}        
				}   
				



<span style="font-family: 微軟雅黑;">使用Volley加載JSON數據幾種方式</span>
import java. util.Map ;

import org.json.JSONException;
import org. json.JSONObject ;

import android. app.Activity ;
import android. os.Bundle ;

import com. android.volley .AuthFailureError;
import com. android.volley .Request. Method;
import com. android.volley .RequestQueue;
import com. android.volley .Response;
import com. android.volley .Response. ErrorListener;
import com. android.volley .Response. Listener;
import com. android.volley .VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com. android.volley .toolbox. JsonObjectRequest;
import com.android.volley.toolbox.JsonRequest;
import com. android.volley .toolbox. StringRequest;
import com. android.volley .toolbox. Volley;
import com. lb.myvolley .R;
import com. lb.myvolley .commom. Constants;

/***
 * 加載網絡數據( json數據)
 * **/
public class StringMainActivity extends Activity {
       private RequestQueue queue;

       @Override
       protected void onCreate(Bundle savedInstanceState) {
             super. onCreate(savedInstanceState) ;
             setContentView(R. layout.activity_main );
             queue = Volley. newRequestQueue(StringMainActivity .this );
             initStringQuest();
             try {
                   initJSONObject();
             } catch (Exception e) {
                   // TODO Auto-generated catch block
                   e.printStackTrace() ;
             }
       }

       /***
       * StringQuest的用法 主要就是進行了以下三步操作:
       *
       * 1. 創建一個RequestQueue對象。
       *
       * 2. 創建一個StringRequest對象。
       *
       * 3. 將StringRequest對象添加到RequestQueue裏面。
       * **/
       private void initStringQuest() {
             // 第二步
             StringRequest request = new StringRequest( Method.POST ,
                         Constants.URL_HEAD , new Listener<String> () {
                               @Override
                               public void onResponse(String response) {
                                     System.out .println(response );
                               }
                         }, new ErrorListener() {
                               @Override
                               public void onErrorResponse(VolleyError error) {
                               }
                         }) {

                   // 重寫getParams()方法,在這裏設置POST參數就可以提交給服務器的參數
                   @Override
                   protected Map <String, String> getParams() throws AuthFailureError {
                         Map<String, String> map = new HashMap <String, String>();
                         map.put( "params1", "value1");
                         map.put( "params2", "value2");
                         return super .getParams() ;
                   }
             };
             // 第三部
             queue.add( request);
       }

       /****
       * . JsonRequest的用法
       * 類似於StringRequest,JsonRequest也是繼承自Request類的,不過由於JsonRequest是一個抽象類
       * ,因此我們無法直接創建它的實例
       * ,那麼只能從它的子類入手了。JsonRequest有兩個直接的子類,JsonObjectRequest和JsonArrayRequest
       * ,從名字上你應該能就看出它們的區別了吧?一個是用於請求一段JSON數據的,一個是用於請求一段JSON數組的
       * ********/
       private void initJSONObject() throws Exception {
             // JSONObject 用來存放數據提交給服務器
             JSONObject obj = new JSONObject() ;
             obj.put( "key", "value");
             JsonObjectRequest objRequest = new JsonObjectRequest( "", obj,
                         new Listener <JSONObject>() {

                               @Override
                               public void onResponse(JSONObject response) {

                               }
                         }, new Response .ErrorListener() {

                               @Override
                               public void onErrorResponse(VolleyError error) {

                               }
                         });
             queue.add( objRequest);
       }

}



使用Volley加載網絡圖片

我們平時在開發Android應用的時候不可避免地都需要用到網絡技術,而多數情況下應用程序都會使用HTTP協議來發送和接收網絡數據。Android系統中主要提供了兩種方式來進行HTTP通信,HttpURLConnection和HttpClient,幾乎在任何項目的代碼中我們都能看到這兩個類的身影,使用率非常高。

不過HttpURLConnection和HttpClient的用法還是稍微有些複雜的,如果不進行適當封裝的話,很容易就會寫出不少重複代碼。於是乎,一些Android網絡通信框架也就應運而生,比如說AsyncHttpClient,它把HTTP所有的通信細節全部封裝在了內部,我們只需要簡單調用幾行代碼就可以完成通信操作了。再比如Universal-Image-Loader,它使得在界面上顯示網絡圖片的操作變得極度簡單,開發者不用關心如何從網絡上獲取圖片,也不用關心開啓線程、回收圖片資源等細節,Universal-Image-Loader已經把一切都做好了。

Android開發團隊也是意識到了有必要將HTTP的通信操作再進行簡單化,於是在2013年Google I/O大會上推出了一個新的網絡通信框架——Volley。Volley可是說是把AsyncHttpClient和Universal-Image-Loader的優點集於了一身,既可以像AsyncHttpClient一樣非常簡單地進行HTTP通信,也可以像Universal-Image-Loader一樣輕鬆加載網絡上的圖片。除了簡單易用之外,Volley在性能方面也進行了大幅度的調整,它的設計目標就是非常適合去進行數據量不大,但通信頻繁的網絡操作,而對於大數據量的網絡操作,比如說下載文件等,Volley的表現就會非常糟糕。
import android. app.Activity ;
import android. graphics.Bitmap ;
import android. graphics.Bitmap .Config;
import android. os.Bundle ;
import android. widget.ImageView ;

import com. android.volley .RequestQueue;
import com. android.volley .Response. ErrorListener;
import com. android.volley .Response. Listener;
import com. android.volley .VolleyError;
import com. android.volley .toolbox. ImageLoader;
import com. android.volley .toolbox. ImageLoader.ImageListener ;
import com. android.volley .toolbox. ImageRequest;
import com. android.volley .toolbox. NetworkImageView;
import com. android.volley .toolbox. Volley;
import com. lb.myvolley .R;
import com. lb.myvolley .utils. BitmapCache;

/****
 * 下載圖片
 * *******/
public class ImageActivity extends Activity {
       private RequestQueue queue;
       private ImageView imgView;
       private NetworkImageView networkImageView ;

       @Override
       protected void onCreate(Bundle savedInstanceState) {
             super. onCreate(savedInstanceState) ;
             setContentView(R. layout.activity_image );
             imgView = (ImageView ) findViewById( R.id .imageView1) ;
             queue = Volley. newRequestQueue(ImageActivity .this );
       }

       /**
       * 使用場景,單張圖片 步驟 1. 創建一個RequestQueue對象。
       *
       * 2. 創建一個Request對象。
       *
       * 3. 將Request對象添加到RequestQueue裏面。
       * **/
       private void initImageRequestQueue() {
             /*****
             * 第一個參數爲URL 第二個爲Listener <Bitmap>回調 第三第四個參數分別用於指定允許圖片最大的寬度和高度
             * 第五個參數用於指定圖片的顏色屬性,Bitmap.Config下的幾個常量都可以在這裏使用,其中ARGB_8888可以展示最好的顏色屬性
             * 第六個參數是圖片請求失敗的回調,這裏我們當請求失敗時在ImageView中顯示一張默認圖片
             * */
             ImageRequest request = new ImageRequest( "圖片地址" , new Listener<Bitmap>() {

                   @Override
                   public void onResponse(Bitmap response) {
                         // 此處設置圖片
                   }
             }, 300, 300, Config. ARGB_8888, new ErrorListener() {

                   @Override
                   public void onErrorResponse(VolleyError error) {

                   }
             });
             queue.add( request);
       }

       /*****
       * 多張圖片並可以添加到緩存 步驟 1. 創建一個RequestQueue對象。
       *
       * 2. 創建一個ImageLoader對象。
       *
       * 3. 獲取一個ImageListener對象。
       *
       * 4. 調用ImageLoader的get()方法加載網絡上的圖片。
       * ***/
       private void initImageLoader() {
             ImageLoader loader = new ImageLoader(queue , new BitmapCache());
             // 第一個參數爲imageViewK控件,第二個爲默認圖片,第三個爲失敗顯示的圖片
             ImageListener listener = ImageLoader.getImageListener (imgView,
                         R.drawable .ic_launcher, R. drawable.ic_launcher );
             loader.get( "圖片地址" , listener );
       }

       /**
       * 最簡單的推薦方式 1. 創建一個RequestQueue對象。
       *
       * 2. 創建一個ImageLoader對象。
       *
       * 3. 在佈局文件中添加一個NetworkImageView控件。 4. 在代碼中獲取該控件的實例。
       *
       * 5. 設置要加載的圖片地址。
       * ***/
       private void initNetWorkImage() {
             ImageLoader imageLoader = new ImageLoader(queue , new BitmapCache());
             networkImageView=( NetworkImageView) findViewById(R. id.network_image_view );
             //默認顯示圖片
             networkImageView.setDefaultImageResId( R.drawable .ic_launcher) ;
             //失敗後顯示的圖片
             networkImageView.setErrorImageResId( R.drawable .ic_launcher) ;
             networkImageView.setImageUrl( "https://img-my.csdn.net/uploads/201404/13/1397393290_5765.jpeg" ,
                                     imageLoader);
       }
}






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