免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5216 | 回复: 1
打印 上一主题 下一主题

Android·HTTP超时机制 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-01-11 15:23 |只看该作者 |倒序浏览
Android·HTTP超时机制






由于手机端应用的响应,与当时的无线通信网络状况有很大的关联。而通信网络往往具有不稳定,延迟长的特点。所以,在我们的应用程序中,当我们请求网络的时候,超时机制的应用就显得特别重要。
超时机制主要有:
1、HTTP请求超时机制
2、Socket通信超时机制
HTTP请求超时机制


Java代码
  1. 1.public static void main(String[] args){   
  2. 2.  
  3. 3.long a=System.currentTimeMillis();   
  4. 4.try{   
  5. 5.URL myurl = new URL(“http://www.baidu.cn”);   
  6. 6.URLConnection myurlcon = myurl.openConnection();   
  7. 7.myurlcon.setConnectTimeout(1000);   
  8. 8.myurlcon.setReadTimeout(1000);   
  9. 9.BufferedReader in = new BufferedReader(new InputStreamReader(myurlcon.getInputStream(),”UTF-8″));   
  10. 10.String inputLine;   
  11. 11.  
  12. 12.while ((inputLine = in.readLine()) != null){   
  13. 13.System.out.println(inputLine);   
  14. 14.in.close();   
  15. 15.System.out.println(System.currentTimeMillis()-a);   
  16. 16.}   
  17. 17.} catch (MalformedURLException e) {   
  18. 18.e.printStackTrace();   
  19. 19.} catch (UnsupportedEncodingException e) {   
  20. 20.e.printStackTrace();   
  21. 21.} catch (IOException e) {   
  22. 22.e.printStackTrace();   
  23. 23.}   
  24. 24.  
  25. 25.}   
  26. 26.  
  27. 27.  
  28. 28.如果超时 将 抛出 以下 异常   
  29. 29.  
  30. 30.java.net.SocketTimeoutException: Read timed out   
  31. 31.at java.net.SocketInputStream.socketRead0(Native Method)   
  32. 32.at java.net.SocketInputStream.read(SocketInputStream.java:129)   
  33. 33.at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)   
  34. 34.at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)   
  35. 35.at java.io.BufferedInputStream.read(BufferedInputStream.java:313)   
  36. 36.at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:606)   
  37. 37.at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:554)   
  38. 38.at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:940)   
  39. 39.at com.Test.main(Test.java:52)  
  40. public static void main(String[] args){

  41. long a=System.currentTimeMillis();
  42. try{
  43. URL myurl = new URL(“http://www.baidu.cn”);
  44. URLConnection myurlcon = myurl.openConnection();
  45. myurlcon.setConnectTimeout(1000);
  46. myurlcon.setReadTimeout(1000);
  47. BufferedReader in = new BufferedReader(new InputStreamReader(myurlcon.getInputStream(),”UTF-8″));
  48. String inputLine;

  49. while ((inputLine = in.readLine()) != null){
  50. System.out.println(inputLine);
  51. in.close();
  52. System.out.println(System.currentTimeMillis()-a);
  53. }
  54. } catch (MalformedURLException e) {
  55. e.printStackTrace();
  56. } catch (UnsupportedEncodingException e) {
  57. e.printStackTrace();
  58. } catch (IOException e) {
  59. e.printStackTrace();
  60. }

  61. }
复制代码
如果超时 将 抛出 以下 异常
  1. java.net.SocketTimeoutException: Read timed out
  2. at java.net.SocketInputStream.socketRead0(Native Method)
  3. at java.net.SocketInputStream.read(SocketInputStream.java:129)
  4. at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
  5. at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
  6. at java.io.BufferedInputStream.read(BufferedInputStream.java:313)
  7. at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:606)
  8. at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:554)
  9. at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:940)
  10. at com.Test.main(Test.java:52)
复制代码
补充内容:
在android项目中,如果有用到http请求,就必须也应该加上http请求的超时管理,异常管理,项目中遇到这个需求,google上搜索到了一大堆,但是写的都比较简单,做个demo还行,用在项目中还是不够完善。自己写了一个例子,有不完善之处,欢迎大家指正。
  需要注意的地方:有三个方面
  如何控制超时机制
  如何处理异常
  如何处理请求错误的


Java代码
  1. 1.private class XmlAsyncLoader extends XmlResourceRequest {   
  2. 2.  
  3. 3. private boolean mIsCancle = false;   
  4. 4. private HttpGet mGet;   
  5. 5. private HttpClient mHttp;   
  6. 6.  
  7. 7. public XmlAsyncLoader(MxActivity<?> activity, String url)   
  8. 8. throws MalformedURLException {   
  9. 9. super(activity, url);   
  10. 10. }   
  11. 11.  
  12. 12. @Override  
  13. 13. protected void doTaskInBackground() {   
  14. 14. // 请求数据   
  15. 15. if (mUrl.toLowerCase().startsWith("http://")) {   
  16. 16. mGet = initHttpGet(mUrl);   
  17. 17. mHttp = initHttp();   
  18. 18. try {   
  19. 19. HttpResponse response = mHttp.execute(mGet);   
  20. 20. if (mIsCancle) {   
  21. 21. return;   
  22. 22. }   
  23. 23. if (response != null) {   
  24. 24. if(response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){   
  25. 25. onResponseError("network error");   
  26. 26. Log.v(TAG, "the code is :"+response.getStatusLine().getStatusCode());   
  27. 27. return;   
  28. 28. }   
  29. 29. notifyUpdateProgress(70);   
  30. 30. Document doc = getDocumet(response);   
  31. 31. Element root = doc.getDocumentElement();   
  32. 32. NodeList appList = root   
  33. 33. .getElementsByTagName(Item_ELEMENT_NAME);   
  34. 34. final int len = appList.getLength();   
  35. 35. if (len <= 0) {// 没有items   
  36. 36. onFoundNoItems();   
  37. 37. return;   
  38. 38. }   
  39. 39. for (int i = 0; i < len; i++) {   
  40. 40. Element item = (Element) appList.item(i);   
  41. 41. if (item.getNodeType() == Node.ELEMENT_NODE) {   
  42. 42. HahaItemInfo info = createHahaItemIno(item);   
  43. 43. if (mIsCancle){   
  44. 44. return;   
  45. 45. }   
  46. 46. onFoundItem(info, 80 + 20 * (i + 1) / len);   
  47. 47. addUrlToQueue(info.userIconUrl);   
  48. 48. }   
  49. 49. };   
  50. 50.   
  51. 51. }   
  52. 52. }catch(ConnectTimeoutException e){   
  53. 53. onResponseError("time out");   
  54. 54. } catch (ClientProtocolException e) {   
  55. 55. --mCurrentPage;   
  56. 56. e.printStackTrace();   
  57. 57. } catch (IOException e) {   
  58. 58. --mCurrentPage;   
  59. 59. e.printStackTrace();   
  60. 60. } catch (XmlPullParserException e) {   
  61. 61. --mCurrentPage;   
  62. 62. e.printStackTrace();   
  63. 63. }finally{   
  64. 64. notifyLoadFinish();   
  65. 65. notifyLoadImages();   
  66. 66. mHttp.getConnectionManager().shutdown();   
  67. 67. }   
  68. 68.  
  69. 69. }   
  70. 70. }   
  71. 71.  
  72. 72.  
  73. 73. private HttpClient initHttp() {   
  74. 74. HttpClient client = new DefaultHttpClient();   
  75. 75. client.getParams().setIntParameter(   
  76. 76. HttpConnectionParams.SO_TIMEOUT, TIME_OUT_DELAY); // 超时设置   
  77. 77. client.getParams().setIntParameter(   
  78. 78. HttpConnectionParams.CONNECTION_TIMEOUT, TIME_OUT_DELAY);// 连接超时   
  79. 79. return client;   
  80. 80. }   
  81. 81.  
  82. 82. private HttpGet initHttpGet(String mUrl) {   
  83. 83. HttpGet get = new HttpGet(mUrl);   
  84. 84. initHeader(get);   
  85. 85. return get;   
  86. 86. }   
  87. 87.  
  88. 88.  
  89. 89. @Override  
  90. 90. public boolean tryCancel() {   
  91. 91. Log.i(TAG, "tryCanle is working");   
  92. 92. mGet.abort();   
  93. 93. mIsCancle = true;   
  94. 94. mHttp.getConnectionManager().shutdown();   
  95. 95. notifyLoadFinish();   
  96. 96. return true;   
  97. 97. }   
  98. 98.  
  99. 99. }  
  100. private class XmlAsyncLoader extends XmlResourceRequest {

  101. private boolean mIsCancle = false;
  102. private HttpGet mGet;
  103. private HttpClient mHttp;

  104. public XmlAsyncLoader(MxActivity<?> activity, String url)
  105. throws MalformedURLException {
  106. super(activity, url);
  107. }

  108. @Override
  109. protected void doTaskInBackground() {
  110. // 请求数据
  111. if (mUrl.toLowerCase().startsWith("http://")) {
  112. mGet = initHttpGet(mUrl);
  113. mHttp = initHttp();
  114. try {
  115. HttpResponse response = mHttp.execute(mGet);
  116. if (mIsCancle) {
  117. return;
  118. }
  119. if (response != null) {
  120. if(response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){
  121. onResponseError("network error");
  122. Log.v(TAG, "the code is :"+response.getStatusLine().getStatusCode());
  123. return;
  124. }
  125. notifyUpdateProgress(70);
  126. Document doc = getDocumet(response);
  127. Element root = doc.getDocumentElement();
  128. NodeList appList = root
  129. .getElementsByTagName(Item_ELEMENT_NAME);
  130. final int len = appList.getLength();
  131. if (len <= 0) {// 没有items
  132. onFoundNoItems();
  133. return;
  134. }
  135. for (int i = 0; i < len; i++) {
  136. Element item = (Element) appList.item(i);
  137. if (item.getNodeType() == Node.ELEMENT_NODE) {
  138. HahaItemInfo info = createHahaItemIno(item);
  139. if (mIsCancle){
  140. return;
  141. }
  142. onFoundItem(info, 80 + 20 * (i + 1) / len);
  143. addUrlToQueue(info.userIconUrl);
  144. }
  145. };

  146. }
  147. }catch(ConnectTimeoutException e){
  148. onResponseError("time out");
  149. } catch (ClientProtocolException e) {
  150. --mCurrentPage;
  151. e.printStackTrace();
  152. } catch (IOException e) {
  153. --mCurrentPage;
  154. e.printStackTrace();
  155. } catch (XmlPullParserException e) {
  156. --mCurrentPage;
  157. e.printStackTrace();
  158. }finally{
  159. notifyLoadFinish();
  160. notifyLoadImages();
  161. mHttp.getConnectionManager().shutdown();
  162. }

  163. }
  164. }


  165. private HttpClient initHttp() {
  166. HttpClient client = new DefaultHttpClient();
  167. client.getParams().setIntParameter(
  168. HttpConnectionParams.SO_TIMEOUT, TIME_OUT_DELAY); // 超时设置
  169. client.getParams().setIntParameter(
  170. HttpConnectionParams.CONNECTION_TIMEOUT, TIME_OUT_DELAY);// 连接超时
  171. return client;
  172. }

  173. private HttpGet initHttpGet(String mUrl) {
  174. HttpGet get = new HttpGet(mUrl);
  175. initHeader(get);
  176. return get;
  177. }


  178. @Override
  179. public boolean tryCancel() {
  180. Log.i(TAG, "tryCanle is working");
  181. mGet.abort();
  182. mIsCancle = true;
  183. mHttp.getConnectionManager().shutdown();
  184. notifyLoadFinish();
  185. return true;
  186. }

  187. }
复制代码
这是一个异步任务类,发送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关键字
  不管是请求成功,还是失败,都需要关闭链接。

论坛徽章:
0
2 [报告]
发表于 2012-01-12 10:22 |只看该作者
谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP