由於手機端應用的響應,與當時的無線通訊網路狀況有很大的關聯。而通訊網路往往具有不穩定,延遲長的特點。所以,在我們的應用程式中,當我們請求網路的時候,逾時機制的應用就顯得特別重要。
逾時機制主要有:
1、HTTP請求逾時機制
2、Socket通訊逾時機制
HTTP請求逾時機制
public static void main(String[] args){long a=System.currentTimeMillis();try{URL myurl = new URL(“http://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("http://")) { 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關鍵字
不管是請求成功,還是失敗,都需要關閉連結。
轉載自Liudroid的部落格