編輯:關於Android編程
網絡一直是我個人的盲點,前一陣子抽出時間學習了一下Volley網絡工具的使用方法,也透過源碼進行了進一步的學習,有一些心得想分享出來。在Android開發中,成熟的網絡工具不少,Android自帶了HttpClient,還有okhttp,還有koush大神創建的ion開源項目,然後就是google後來加入到Android項目源碼中的Volley。為什麼使用Volley,是因為Volley使用簡單,邏輯清晰,即使在調試過程中出現了問題,也可以快速的通過源碼進行定位。
因為已經習慣了使用Gradle構架應用,所以我在第一次想要使用Volley的時候嘗試尋找是否可以通過gradle的配置文件進行庫依賴。可惜的是,並沒有。但即使這樣Volley的庫也很容易做出來加入到我們的工程中。
首先需要ant編譯工具,然後如果有Android系統源碼的話,Volley在frameworks/volley目錄下。如果沒有Android源碼,也很好辦,可以單獨從Android的倉儲中克隆出Volley源碼:
git clone https://android.googlesource.com/platform/frameworks/volley不幸的是,volley庫的源碼Android並沒有托管在其在Github的帳號上,所以只能在googlesource上進行克隆,當然在國內也就需要先FQ才可以了。
下圖為Volley源碼結構:
克隆成功後,可以方便的使用ant進行編譯,當然,如果是在完整的Android源碼下,也可以直接通過make進行編譯,但是時間必然會長很多。這裡使用ant編譯為例,執行:
ant jar結果如圖所示:
這樣jar包就生成了,很方便吧,接下來將其添加到工程中就可以使用了。
Volley的網絡請求父類為Request
為了更加貼近實際使用,下邊將使用Volley與Cloudant進行通訊做示例。Cloudant是一家提供雲服務業務的公司,其向開發者提供免費的雲存儲、雲數據庫服務。關於其注冊等流程本文不做敘述,很簡單的。直接從登錄開始:
Volley的一個很大的特色,就是所有的網絡請求無需開發者自己執行,而是在請求構造完成後扔到Volley的請求隊列中,隊列依次進行請求,這樣就省去了很多麻煩,開發者也不用擔心網絡請求是否會沖突,是否會在主線程,這些煩心事Volley的網絡隊列都幫我們解決了。
一般來說,一個應用程序如果網絡請求沒有特別頻繁則完全可以只有一個請求隊列(對應Application),如果非常多或其他情況,則可以是一個Activity對應一個網絡請求隊列,具體情況具體分析。下邊的代碼展示了如何申請一個Volley網絡請求隊列:
RequestQueue mQueue; mQueue = Volley.newRequestQueue(getApplicationContext());
這樣就成功申請了一個網絡請求隊列,如果只有一個,則可以在Application中進行申請。
假設已經成功注冊,登錄名foo,密碼bar。
通過查閱Cloudant的登錄認證文檔:https://docs.cloudant.com/api/authn.html。可以發現Cloudant登錄認證相關接口有三個:
這裡我們使用POST方法進行cookie登錄認證。結合上邊假設的用戶名和密碼可知:
要訪問的url為 foo.cloudant.com/_session 頭信息為 Content-Type: application/x-www-form-urlencoded 參數為 name = foo, password = bar
若訪問成功,我們就可以在網絡回應中獲取cookie,以備之後其他操作使用。顯然,這個請求跟json毫無關系,應該使用StringRequest,StringRequest有兩種構造方法:
public StringRequest(int method, String url, Listener第二個方法只有GET請求才可以使用,第一個方法的method參數可以用來自定義請求類型,這裡我們需要的是POST,所以應該使用第一個構造方法:listener, ErrorListener errorListener) public StringRequest(String url, Listener listener, ErrorListener errorListener)
StringRequest request = new StringRequest( Request.Method.POST, http://foo.cloudant.com/_session, new Response.Listener() { @Override public void onResponse(String s) { //收到成功應答後會觸發這裡 } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { //出現連接錯誤會觸發這裡 } } );
上邊的代碼中,我們成功構造了一個StringRequest,其中已經包含了我們需要的POST和正確的URL,同時還添加了網絡回應監聽器。但是,還缺少文檔要求我們的頭信息和參數。StringRequest在構造中並不提供這些信息的定義,這也是與其他常用網絡工具不同的地方,剛接觸的同學可能會很不適用,通過復寫StringRequest的兩個方法就可以將這些信息放進去了。下邊來完善這個請求:
StringRequest request = new StringRequest( Request.Method.POST, http://foo.cloudant.com/_session, new Response.Listener() { @Override public void onResponse(String s) { } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { } } ) { @Override public Map getHeaders() throws AuthFailureError { //設置頭信息 Map map = new HashMap (); map.put(Content-Type, application/x-www-form-urldecoded); return map; } @Override protected Map getParams() throws AuthFailureError { //設置參數 Map map = new HashMap (); map.put(name, foo); map.put(password, bar); return map; } };
相比第一次我們的構造過程,這一次多了兩個復寫的方法來設置頭信息和參數,很容易吧。這個時候請求基本完成了,但是卻缺少另一個很重要的東西,我們的登錄認證為的是拿回屬於自己的cookie,如果不能獲取cookie的話,多麼正確的請求格式都是白費力氣啊,想要拿到cookie一樣也是通過復寫另一個方法進行獲取:
@Override protected Response在網絡請求成功後,服務端返回應答信息,而我們所需的Cookie信息就在這些應答信息中,通過對應答信息的遍歷查找,很方便就可以找到我們所需的信息了。到這裡,我們的登錄認證請求就構造完成了,最後需要做的就是將這個StringRequest扔到我們的請求隊列中去:parseNetworkResponse(NetworkResponse response) { for (String s : response.headers.keySet()) { if (s.contains(Set-Cookie)) { mCookie = response.headers.get(s); break; } } return super.parseNetworkResponse(response); }
mQueue.add(request);網絡通暢的情況下,很快就能夠獲取Cookie信息了。
在注冊Cloudant成功後,Cloudant會在我們的帳號中創建一個默認數據庫——crud,其中保存著一行測試數據welcome。
讓我們用Volley來訪問這條數據。查閱Cloudant API文檔Documents相關可以發現:
通過簡單的GET請求搭配正確的URL即可得到文件(數據)內容,當然,這一切的前提是我們已經掌握了正確的Cookie數據。那麼,我們需要:
1. 請求頭數據中包含正確的Cookie信息 2. 訪問正確的URL 3. 請求類型:GET假設通過上一步登陸認證後我們將Cookie信息保存在了mCookie字符串變量中。而我們需要訪問的URL通過查閱文檔也可以得出路徑為 數據庫名 + 文檔名,即foo.cloudant.com/crud/welcome。萬事俱備,使用StringRequest:
StringRequest request = new StringRequest( http://foo.cloudant.com/crud/welcome, new Response.Listener() { @Override public void onResponse(String s) { } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { } } ) { @Override public Map getHeaders() throws AuthFailureError { Map map = new HashMap (); map.put(Cookie, mCookie); return map; } }; mQueue.add(request);
簡單的網絡請求StringRequest完全處理得來,使用也比較簡單,就介紹到這裡。下邊介紹JsonObjectRequest應用方法。
public JsonObjectRequest(int method, String url, JSONObject jsonRequest, Listener第一種方法參數以此為:請求方法,訪問的URL,Json數據對象,請求成功監聽器,請求失敗監聽器。 第二種構造方法中,若jsonRequest為空,則方法自動為GET,不為空則自動切換為POST,其他參數含義相同。listener, ErrorListener errorListener) public JsonObjectRequest(String url, JSONObject jsonRequest, Listener listener, ErrorListener errorListener)
1. 訪問的URL path為數據庫目錄 2. Content-Type被要求為application/json 3. 攜帶的數據要求為json數據
既然方法要求為POST,我們又是創建數據,肯定數據內容不會為空,所以我們選擇第二種構造方法。首先,創建一個Json對象:
JSONObject jsonObject = new JSONObject(); jsonObject.put(_id, testinfo); jsonObject.put(person, foo); jsonObject.put(phone, bar);
JsonObjectRequest request = new JsonObjectRequest( http://foo.cloudant.com/crud, jsonObject, new Response.Listener() { @Override public void onResponse(JSONObject jsonObject) { } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { } } ) { @Override public Map getHeaders() throws AuthFailureError { Map map = new HashMap (); map.put(Cookie, mCookie); return map; } }; mQueue.add(request);
@Override public String getBodyContentType() { return PROTOCOL_CONTENT_TYPE; }
/** Charset for request. */ private static final String PROTOCOL_CHARSET = utf-8; /** Content type for request. */ private static final String PROTOCOL_CONTENT_TYPE = String.format(application/json; charset=%s, PROTOCOL_CHARSET);
安裝Android Studio相關教程(不翻牆版)這篇文章是當年自己剛用android studio時寫的,主要是當時同班同學問題太多,後來我直接寫了這篇。現在發上來給
准備需要下載ntfs-3g驅動包,並做相應修改,這個網上已經可以下載到修改好的包,本文最後也會附加。為什麼要移植在Android原生代碼中,只支持了FAT格式的掛載,並未
Android模擬器安裝APP出現INSTALL_FAILED_NO_MATCHING_ABIS錯誤解決方案當我們想在電腦的Android模擬器中安裝APP的
作為Android四大組件之一,Activity可以說是最基本也是最常見的組件,它提供了一個顯示界面,從而實現與用戶的交互,作為初學者,必須熟練掌握。今天我們就來通過實驗