閱讀408 返回首頁    go 魔獸


Android·HTTP超時機製

由於手機端應用的響應,與當時的無線通信網絡狀況有很大的關聯。而通信網絡往往具有不穩定,延遲長的特點。所以,在我們的應用程序中,當我們請求網絡的時候,超時機製的應用就顯得特別重要。

超時機製主要有:

1、HTTP請求超時機製

2、Socket通信超時機製

HTTP請求超時機製

public static void main(String[] args){

long a=System.currentTimeMillis();
try{
URL myurl = new URL(“https://www.baidu.cn”);
URLConnection myurlcon = myurl.openConnection();
myurlcon.setConnectTimeout(1000);
myurlcon.setReadTimeout(1000);
BufferedReader in = new BufferedReader(new InputStreamReader(myurlcon.getInputStream(),”UTF-8″));
String inputLine;

while ((inputLine = in.readLine()) != null){
System.out.println(inputLine);
in.close();
System.out.println(System.currentTimeMillis()-a);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

}


如果超時 將 拋出 以下 異常

java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
at java.io.BufferedInputStream.read(BufferedInputStream.java:313)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:606)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:554)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:940)
at com.Test.main(Test.java:52)


補充內容:

在android項目中,如果有用到http請求,就必須也應該加上http請求的超時管理,異常管理,項目中遇到這個需求,google上搜索到了一大堆,但是寫的都比較簡單,做個demo還行,用在項目中還是不夠完善。自己寫了一個例子,有不完善之處,歡迎大家指正。

  需要注意的地方:有三個方麵

  如何控製超時機製

  如何處理異常

  如何處理請求錯誤的 

private class XmlAsyncLoader extends XmlResourceRequest {

 private boolean mIsCancle = false;
 private HttpGet mGet;
 private HttpClient mHttp;

 public XmlAsyncLoader(MxActivity<?> activity, String url)
 throws MalformedURLException {
 super(activity, url);
 }

 @Override
 protected void doTaskInBackground() {
 // 請求數據
 if (mUrl.toLowerCase().startsWith("https://")) {
 mGet = initHttpGet(mUrl);
 mHttp = initHttp();
 try {
 HttpResponse response = mHttp.execute(mGet);
 if (mIsCancle) {
 return;
 }
 if (response != null) {
 if(response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){
 onResponseError("network error");
 Log.v(TAG, "the code is :"+response.getStatusLine().getStatusCode());
 return;
 }
 notifyUpdateProgress(70);
 Document doc = getDocumet(response);
 Element root = doc.getDocumentElement();
 NodeList appList = root
 .getElementsByTagName(Item_ELEMENT_NAME);
 final int len = appList.getLength();
 if (len <= 0) {// 沒有items
 onFoundNoItems();
 return;
 }
 for (int i = 0; i < len; i++) {
 Element item = (Element) appList.item(i);
 if (item.getNodeType() == Node.ELEMENT_NODE) {
 HahaItemInfo info = createHahaItemIno(item);
 if (mIsCancle){
 return;
 }
 onFoundItem(info, 80 + 20 * (i + 1) / len);
 addUrlToQueue(info.userIconUrl);
 }
 };
 
 }
 }catch(ConnectTimeoutException e){
 onResponseError("time out");
 } catch (ClientProtocolException e) {
 --mCurrentPage;
 e.printStackTrace();
 } catch (IOException e) {
 --mCurrentPage;
 e.printStackTrace();
 } catch (XmlPullParserException e) {
 --mCurrentPage;
 e.printStackTrace();
 }finally{
 notifyLoadFinish();
 notifyLoadImages();
 mHttp.getConnectionManager().shutdown();
 }

 }
 }


 private HttpClient initHttp() {
 HttpClient client = new DefaultHttpClient();
 client.getParams().setIntParameter(
 HttpConnectionParams.SO_TIMEOUT, TIME_OUT_DELAY); // 超時設置
 client.getParams().setIntParameter(
 HttpConnectionParams.CONNECTION_TIMEOUT, TIME_OUT_DELAY);// 連接超時
 return client;
 }

 private HttpGet initHttpGet(String mUrl) {
 HttpGet get = new HttpGet(mUrl);
 initHeader(get);
 return get;
 }


 @Override
 public boolean tryCancel() {
 Log.i(TAG, "tryCanle is working");
 mGet.abort();
 mIsCancle = true;
 mHttp.getConnectionManager().shutdown();
 notifyLoadFinish();
 return true;
 }

 }



 


這是一個異步任務類,發送get請求請求數據,解析服務器的響應數據,同時通知ui線程更新ui

在android中,互聯網交互的寫法有很多,可以使用apache提供的包,也可以使用google提供的api,我不知道那種更好,隻是習慣於使用
apache的api。
1. 設置超時機製


client.getParams().setIntParameter( HttpConnectionParams.SO_TIMEOUT, TIME_OUT_DELAY); // 超時設置 client.getParams().setIntParameter( HttpConnectionParams.CONNECTION_TIMEOUT, TIME_OUT_DELAY);// 連接超時

這裏設置了兩種超時,第一種是請求超時,第二種時連接超時。

當向服務器發出請求後,請求和服務器建立socket連接,但是很長時間內都沒有建立socket連接,這就時第一種請求超時,這種情況主要發生在請求了
一個不存在的服務器。超時之後,會拋出InterruptedIOException異常。
Timeout for blocking operations. The argument value is specified in
 milliseconds. An  InterruptedIOException is thrown if this timeout
 expires.
客戶端已經與服務器建立了socket連接,但是服務器並沒有處理客戶端的請求,沒有相應服務器,這就是第二種連接超時。這中超時會拋出
ConnectTimeoutException異常,ConnectTimeoutException繼承自InterruptedIOException,所以隻要捕獲ConnectTimeoutException
就可以了。
2. 分析一下請求的過程
 2.1 HttpResponse response = mHttp.execute(mGet);
執行請求方法,獲取服務器響應,(這裏有個不太成熟的看法,response不可能為null,還有待驗證)。
  2.2 獲取請求響應碼


if(response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){ onResponseError("network error"); Log.v(TAG, "the code is :"+response.getStatusLine().getStatusCode()); return; }
  即使連接上服務器,並且從服務器上獲取了數據,也有可能時服務器返回的錯誤信息,因此也需要特殊處理。
2.3 異常處理
  對於異常,不能簡單的捕獲就完事,例如上麵的代碼中,我請求第三頁的數據,如果發生異常,請求不成功,那麼我就需要讓當前頁數回滾,
如果成功了就不用回滾了,所以需要對異常進行處理
2.4 finally關鍵字
  不管是請求成功,還是失敗,都需要關閉鏈接。

 

最後更新:2017-04-02 06:52:06

  上一篇:go 關於Linux靜態庫和動態庫的分析
  下一篇:go Android-telephony各文件解釋 電話係統之rilD Android電話係統之RIL-Java