Android 關於網絡操做通常都會介紹 HttpClient 以及 HttpConnection 這兩個包。前者是 Apache 開源庫,後者是 Android 自帶 API。企業級應用,通常都會選擇使用已經封裝好的 http 框架。比較流行有 Volley、android-async-http、retrofit、okhttp、androidquery、AndroidAsync 等。他們各有特色,不一樣的框架有不一樣的效率,現在 Google 推出了官方的針對 Android 平臺上的網絡通訊庫 Volley,能使網絡通訊更快,更簡單,更健壯,Volley 在提供了高性能網絡通信功能的同時,對網絡圖片加載也提供了良好的支持,徹底能夠知足簡單 REST 客戶端的需求。另外,但 Volley 擴展性很強,能夠根據須要定製你本身的網絡請求。css
Volley 是 Ficus Kirpatrick 在 Gooogle I/O 2013 發佈的一個處理和緩存網絡請求的庫,能使網絡通訊更快,更簡單,更健壯。Volley 名稱的由來 a burst or emission of many things or a large amount at once。在Gooogle I/O 2013 演講上,其配圖是一幅火弓箭。如圖 1 所示。html
圖 1 Gooogle I/O 2013 Volleyandroid
Volley 管理着處理和緩存網絡請求,它節省了開發者的寶貴時間,一次又一次編寫相同的網絡調用/緩存代碼。更少的重複代碼,其中一個好處就是減小了 bug,這是全部開發者所指望的。git
所謂「一次又一次編寫相同的網絡調用/緩存代碼」,就是 AsyncTask 以及你編寫的經過 Web API 獲取響應,並顯示出來的邏輯/代碼。咱們必須在 ProgressBar() 和 onPostExecute() 方法內照顧 ProgressBar/ProgressDialog 。雖然這不是一個艱鉅的任務,但卻很無聊,甚至感到厭倦,儘管我已經定義了 BaseTask 類來管理ProgressBar/ProgressDialog 的顯示/取消,以及更多其它操做。如今,Volley 是替代 AsyncTask 的強大工具。github
Volley 適合小而快的數據傳輸,特別是針對如下兩種狀況:json
Volley 優點:緩存
- Volley 能夠自動安排全部的網絡請求。這意味着 Volley 會照顧你 APP 執行的從 Web 獲取響應或圖片全部的網絡請求。
- Volley 提供透明的磁盤和內存緩存。
- Volley 提供強大的取消請求的 API。這意味着你能夠取消一個單獨的請求,或是你能夠設置取消請求的塊(能夠爲多個)或範圍。
- Volley 提供強大的自定功能。
- Volley 提供調試和追蹤工具。
Volley 使用了線程池來做爲基礎結構,主要分爲主線程,cache 線程和 network 線程。主線程和 cache 線程都只有一個,而 NetworkDispatcher 線程能夠有多個,這樣能解決比並行問題。網絡
圖 2 Volley 架構架構
下載演示,將 Volley 庫和演示項目導入到 eclipse 裏,再將 Volley 庫添加到演示項目。程序運行結果如圖 3 所示,包含兩個演示:網絡獲取 JSON 和 圖片。app
圖 3 左:程序主界面;中:點擊「獲取 JSON」;右:點擊「獲取 Image」
主程序 activity_main.xml 界面包含兩個按鈕,顯示兩個演示的 activity,核心代碼以下所示:
public class MainActivity extends Activity {
Intent intent = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_json).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
intent = new Intent(MainActivity.this, JsonDemo.class);
startActivity(intent);
}
});
findViewById(R.id.btn_img).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
intent = new Intent(MainActivity.this, ImgDemo.class);
startActivity(intent);
}
});
}
}
修改 AndroidManifest.xml 文件,添加受權 Android 訪問網絡的權限。
<uses-permission android:name="android.permission.INTERNET" />
經過 Volley 訪問國家氣象局提供的 JSON 接口,得到北京的天氣情況。
activity_json.xml 頁面文件包含一個 TextView 控件和一個 ProgreeBar 控件,略,核心代碼以下所示:
package com.example.volleyexample;
import android.app.Activity;
import org.json.JSONObject;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class JsonDemo extends Activity {
private TextView txtDisplay;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_json);
txtDisplay = (TextView) findViewById(R.id.txtDisplay);
RequestQueue queue = Volley.newRequestQueue(this);
String url = "http://www.weather.com.cn/data/sk/101010100.html";
JsonObjectRequest jsObjRequest = new JsonObjectRequest(
Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
// TODO Auto-generated method stub
txtDisplay.setText("Response => " + response.toString());
findViewById(R.id.progressBar1)
.setVisibility(View.GONE);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
}
});
queue.add(jsObjRequest);
}
}
activity_img.xml 頁面文件包含兩個控件:ImageView 和 NetworkImageView,其中,NetworkImageView 是 Volley 提供的控件,畢竟加載圖片的使用頻率很高,略,核心代碼以下所示:
package com.example.volleyexample;
import org.json.JSONObject;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageCache;
import com.android.volley.toolbox.ImageLoader.ImageListener;
import com.android.volley.toolbox.NetworkImageView;
import com.android.volley.toolbox.Volley;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.util.LruCache;
import android.widget.ImageView;
public class ImgDemo extends Activity {
String url = "http://images.cnblogs.com/cnblogs_com/liuning8023/588559/o_Android.jpg";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_img);
RequestQueue mRequestQueue = Volley.newRequestQueue(this);
final LruCache<String, Bitmap> mImageCache = new LruCache<String, Bitmap>(
20);
ImageCache imageCache = new ImageCache() {
@Override
public void putBitmap(String key, Bitmap value) {
mImageCache.put(key, value);
}
@Override
public Bitmap getBitmap(String key) {
return mImageCache.get(key);
}
};
ImageLoader mImageLoader = new ImageLoader(mRequestQueue, imageCache);
// ImageView
ImageView img = (ImageView) findViewById(R.id.imgView);
ImageListener listener = ImageLoader
.getImageListener(img, android.R.drawable.ic_menu_rotate,
android.R.drawable.ic_delete);
mImageLoader.get(url, listener);
// NetworkImageView
NetworkImageView netImgView = (NetworkImageView) findViewById(R.id.networkImgView);
netImgView.setTag("url");
netImgView.setImageUrl(url, mImageLoader);
}
}