最近做項目要求使用到網路,想來想去選擇了AsyncHttpClient框架開進行APP開發。在這裡把我工作期間遇到的問題以及對AsyncHttpClient的使用經驗做出相應總結,希望能對您的學習有所幫助。 首先按照慣例先來簡單瞭解一些AsyncHttpClient網路框架的一些知識。 1、簡介 A ...
最近做項目要求使用到網路,想來想去選擇了AsyncHttpClient框架開進行APP開發。在這裡把我工作期間遇到的問題以及對AsyncHttpClient的使用經驗做出相應總結,希望能對您的學習有所幫助。
首先按照慣例先來簡單瞭解一些AsyncHttpClient網路框架的一些知識。
1、簡介
Android中網路請求一般使用Apache HTTP Client或者採用HttpURLConnect,但是直接使用這兩個類庫需要寫大量的代碼才能完成網路post和get請求,而使用android-async-http這個庫可以大大的簡化操作,它是基於Apache’s HttpClient ,所有的請求都是獨立在UI主線程之外,通過回調方法處理請求結果,採用android Handler message 機制傳遞信息。
2、特性
(1)採用非同步http請求,並通過匿名內部類處理回掉結果
(2)http請求獨立在UI主線程之外
(3)採用線程池來處理併發請求
(4)採用RequestParams類創建GET/POST參數
(5)不需要第三方包即可支持Multipart file文件上傳
(6)大小隻有25kb
(7)自動為各種行動電話處理連接斷開時請求重連
(8)超快的自動gzip響應解碼支持
(9)使用BinaryHttpResponseHandler類下載二進位文件(如圖片)
(10)使用JsonHttpResponseHandler類可以自動將響應結果解析為json格式(下麵會重點講解JsonHttpResponseHandler在使用過程中存在的問題)
(11)持久化cookie存儲,可以將cookie保存到你的應用程式的SharedPreferences中
以上的理論源於網友的博客,有興趣的朋友如果想瞭解更多的關於AsyncHttpClient的理論知識可以去參考一下這位網友的博客
《Android網路請求框架AsyncHttpClient詳解》:http://blog.csdn.net/xiaohui2015/article/details/51462782
3、使用辦法
在講解實例之前,請先看介面文檔,結合介面文檔和實例學習起來更清晰。
用戶登錄介面文檔:
介面地址:http://xxx.xxx.xxx/MobileService/userLogin
備註:
請求參數:
{
username:”用戶登錄”,
password:”密碼”
}
返回結果:
{
“code”:”狀態碼”,1000 返回成功 其他失敗
“message”:”提示信息”,
“data”:{
userid:”用戶id”,
supplier:”供應商id”,
suppliername:”供應商名稱”
}
}
1 usercount = (EditText) findViewById(R.id.usernumber); 2 password = (EditText) findViewById(R.id.password);
下麵代碼中的usercount和password是我在界面中定義的兩個EditText類型的控制項。用來輸入用戶的賬號和密碼。
1 AsyncHttpClient client = new AsyncHttpClient(); 2 String url = "http://xxx.xxx.xxx/MobileService/userLogin"; 3 // 使用RequestParams來向介面發送請求的參數,結合介面文檔可以看出我要向伺服器發送的參數為username和password 4 RequestParams params = new RequestParams(); 5 params.put("username", usercount.getText().toString()); 6 params.put("password", password.getText().toString()); 7 // 請註意,在這裡我是用的是AsyncHttpResponseHandler來進行網路處理,而沒有使用JsonHttpResponseHandler來進行處理,原因在下麵講明。 8 //另外需要註意的是這裡一定要用post方式提交,而且在client.的時候千萬不要忘記選擇帶參數params的post,否則你拿什麼和伺服器交流?我就翻過這樣的錯誤。 9 client.post(url, params, new AsyncHttpResponseHandler() { 10 11 @Override 12 public void onSuccess(int arg0, Header[] arg1, byte[] arg2) { 13 // TODO Auto-generated method stub 14 try { 15 // 從伺服器中接收返回的數據,併進行字元集設置,返回的結果集放resultDate中,resultDate相當於一個容器,所有的返回信息都在其中。只要用過JSON解析出來返回值並逐個獲取返回值就OK了。 16 // 不要問我為什麼這麼使用,我也不知道。只清楚這麼好用。 17 String resultDate = new String(arg2, "utf-8"); 18 // 結合介面文檔可以看出返回的結果都是單個的,沒有返回的是集合或數組這樣多個的情況,所以直接用JSONObject來接受返回值即可 19 JSONObject js = new JSONObject(resultDate); 20 // 將code、message、data解析出來。對於返回值是單個的而不是集合或數組的取值方式有兩種。1:js.getJSONObject("xxx");2:js.getString("xxx");xxx代表任意String類型的字元串 21 //通過介面文檔可以看出,返回值都是String類型的數據,所以我在這裡選擇了第二種取值方式,如果使用第一種會造成類型不匹配而導致程式錯誤。 22 String code = js.getString("code"); 23 String message = js.getString("message"); 24 String data = js.getString("data"); 25 //對data中的數據進行進一步的解析,原理同上面一樣 26 JSONObject jsonObject = new JSONObject(data); 27 String userid = jsonObject.getString("userid"); 28 String supplier = jsonObject.getString("supplier"); 29 String suppliername = jsonObject.getString("suppliername"); 30 //1000代表狀態碼,表示登陸成功 31 if ("1000".equals(code)) { 32 //使用SharedPreferences將用戶的賬戶和密碼存儲起來,關於SharedPreferences的存儲知識請參考我的另外一篇文章 33 SharedPreferences sharedPreferences = getSharedPreferences( 34 message, Activity.MODE_PRIVATE); 35 Editor editor = sharedPreferences.edit(); 36 editor.putString("username", usercount.getText() 37 .toString()); 38 editor.putString("password", password.getText() 39 .toString()); 40 editor.commit(); 41 Intent intent = new Intent(getApplicationContext(), 42 MainActivity.class); 43 intent.putExtra("userid", userid.toString()); 44 startActivity(intent); 45 } else { 46 Toast.makeText(getApplicationContext(), "賬號或密碼錯誤", 47 Toast.LENGTH_LONG).show(); 48 } 49 } catch (UnsupportedEncodingException e) { 50 // TODO Auto-generated catch block 51 e.printStackTrace(); 52 } catch (JSONException e) { 53 // TODO Auto-generated catch block 54 e.printStackTrace(); 55 } 56 57 } 58 59 @Override 60 public void onFailure(int arg0, Header[] arg1, byte[] arg2, 61 Throwable arg3) { 62 // TODO Auto-generated method stub 63 Toast.makeText(getApplicationContext(), "請檢查網路!", 64 Toast.LENGTH_SHORT).show(); 65 } 66 }); 67
上面的代碼是通過AsyncHttpResponseHandler()來處理伺服器的返回值的,AsyncHttpClient中還有一個用來處理伺服器的返回值,我看大多數博客都寫的是這個JsonHttpResponseHandler()。
JsonHttpResponseHandler()來處理伺服器返回值的代碼如下:
1 AsyncHttpClient client = new AsyncHttpClient(); 2 String url = "http://xxx.xxx.xxx/MobileService/userLogin"; 3 RequestParams params = new RequestParams(); 4 params.put("username", usercount.getText().toString()); 5 params.put("password", password.getText().toString()); 6 client.post(url, params, new JsonHttpResponseHandler() { 7 @Override 8 public void onSuccess(int statusCode, Header[] headers, 9 JSONObject response) { 10 // TODO Auto-generated method stub 11 super.onSuccess(statusCode, headers, response); 12 try { 13 JSONObject js = new JSONObject(response.toString()); 14 String code = js.getString("code"); 15 16 String message = js.getString("message"); 17 String data = js.getString("data"); 18 19 JSONObject jsonObject = new JSONObject(data); 20 String userid = jsonObject.getString("userid"); 21 String supplier = jsonObject.getString("supplier"); 22 String suppliername = jsonObject.getString("suppliername"); 23 24 if ("1000".equals(code)) { 25 SharedPreferences sharedPreferences = getSharedPreferences( 26 message, Activity.MODE_PRIVATE); 27 Editor editor = sharedPreferences.edit(); 28 editor.putString("username", usercount.getText() 29 .toString()); 30 editor.putString("password", password.getText() 31 .toString()); 32 editor.commit(); 33 Intent intent = new Intent(getApplicationContext(), 34 MainActivity.class); 35 intent.putExtra("userid", userid.toString()); 36 startActivity(intent); 37 } else { 38 Toast.makeText(getApplicationContext(), "賬號或密碼錯誤", 39 Toast.LENGTH_LONG).show(); 40 } 41 42 } catch (JSONException e) { 43 // TODO Auto-generated catch block 44 e.printStackTrace(); 45 } 46 } 47 48 @Override 49 public void onFailure(int statusCode, Header[] headers, 50 Throwable throwable, JSONArray errorResponse) { 51 // TODO Auto-generated method stub 52 super.onFailure(statusCode, headers, throwable, errorResponse); 53 Toast.makeText(getApplicationContext(), "請檢查網路!", 54 Toast.LENGTH_SHORT).show(); 55 } 56 }); 57
請看第6行和第9行代碼,第6行代碼就是使用JsonHttpResponseHandler()來處理傳回的數據的。第9行代碼中的參數response就是上面特性中的第10條:使用JsonHttpResponseHandler類可以自動將響應結果解析為json格式。使用JsonHttpResponseHandler()雖然很方便,但是卻存在著很大的問題。JsonHttpResponseHandler()在使用過程中有時莫名的出現請求不了伺服器的情況,就是onSuccess和onFailure方法都進不去,這樣就直接造成了程式無法正常使用。如果你不信你可以試試,明明前幾分鐘你使用JsonHttpResponseHandler()處理返回數據還好用呢,而你在這期間根本沒有動過其中的代碼,JsonHttpResponseHandler就莫名其妙的不好用了,而且原因不知道,無論你怎麼調試都不成功。相反AsyncHttpResponseHandler()則根本不存在這樣的問題。所以我就果斷的放棄使用JsonHttpResponseHandler(),而採用AsyncHttpResponseHandler()來處理返回數據。當然AsyncHttpClient當中還封裝了不少別的用來處理響應的方法,因為別的本人沒有使用過,具體怎麼樣我也不知道。如果有使用過別的方法的朋友可以在下麵留言告訴我,我們好相互學習。
對於介面返回值是數組或集合的形式有不會的朋友可以參照下麵的代碼,我就不解釋了,反正是照著代碼直接寫肯定沒有問題。
1 AsyncHttpClient client = new AsyncHttpClient(); 2 String url = "http://xxx.xxx.xxx/MobileService/userLogin"; 3 RequestParams params = new RequestParams(); 4 params.add("userid", userid); 5 client.post(url, params, new AsyncHttpResponseHandler() { 6 7 @Override 8 public void onSuccess(int arg0, Header[] arg1, byte[] arg2) { 9 // TODO Auto-generated method stub 10 try { 11 String resultDate = new String(arg2, "utf-8"); 12 JSONObject js1 = new JSONObject(resultDate); 13 String code = js1.getString("code"); 14 String message = js1.getString("message"); 15 String data = js1.getString("data"); 16 JSONObject js2 = new JSONObject(data); 17 if ("1000".equals(code)) { 18 String productlist = js2.getString("productlist"); 19 JSONArray array = new JSONArray(productlist);//productlist返回的數據就是一個集合 20 //List<Map<String, Object>> arrays,這個在全局變數中進行聲明。 21 arrays = new ArrayList<Map<String, Object>>(); 22 for (int i = 0; i < array.length(); i++) { 23 JSONObject js3 = array.getJSONObject(i); 24 String batchnumber = js3.getString("batchnumber"); 25 HashMap<String, Object> map = new HashMap<String, Object>(); 26 map.put("batchnumber", batchnumber); 27 arrays.add(map); 28 } 29 System.out.println("arrays:" + arrays); 30 33 } 34 35 } catch (UnsupportedEncodingException e) { 36 Log.e("log_tag", 37 "Error parsing classname data" + e.toString()); 38 } catch (JSONException e) { 39 // TODO Auto-generated catch block 40 Log.e("log_tag", "Request failed" + e.toString()); 41 } 42 } 43 44 @Override 45 public void onFailure(int arg0, Header[] arg1, byte[] arg2, 46 Throwable arg3) { 47 // TODO Auto-generated method stub 48 Toast.makeText(getApplicationContext(), "服務異常", 49 Toast.LENGTH_SHORT).show(); 50 } 51 }); 52
關於AsyncHttpClient網路框架的使用我的瞭解就是這麼多了,關於JsonHttpResponseHandler()有時候不好用的問題如果誰知道怎麼回事歡迎留言告訴我,鄙人感激不盡。希望這篇博客對大家有所幫助。