Chinaunix
标题:
Android·HTTP超时机制
[打印本页]
作者:
cu_Cbear
时间:
2012-01-11 15:23
标题:
Android·HTTP超时机制
Android·HTTP超时机制
由于手机端应用的响应,与当时的无线通信网络状况有很大的关联。而通信网络往往具有不稳定,延迟长的特点。所以,在我们的应用程序中,当我们请求网络的时候,超时机制的应用就显得特别重要。
超时机制主要有:
1、HTTP请求超时机制
2、Socket通信超时机制
HTTP请求超时机制
Java代码
1.public static void main(String[] args){
2.
3.long a=System.currentTimeMillis();
4.try{
5.URL myurl = new URL(“http://www.baidu.cn”);
6.URLConnection myurlcon = myurl.openConnection();
7.myurlcon.setConnectTimeout(1000);
8.myurlcon.setReadTimeout(1000);
9.BufferedReader in = new BufferedReader(new InputStreamReader(myurlcon.getInputStream(),”UTF-8″));
10.String inputLine;
11.
12.while ((inputLine = in.readLine()) != null){
13.System.out.println(inputLine);
14.in.close();
15.System.out.println(System.currentTimeMillis()-a);
16.}
17.} catch (MalformedURLException e) {
18.e.printStackTrace();
19.} catch (UnsupportedEncodingException e) {
20.e.printStackTrace();
21.} catch (IOException e) {
22.e.printStackTrace();
23.}
24.
25.}
26.
27.
28.如果超时 将 抛出 以下 异常
29.
30.java.net.SocketTimeoutException: Read timed out
31.at java.net.SocketInputStream.socketRead0(Native Method)
32.at java.net.SocketInputStream.read(SocketInputStream.java:129)
33.at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
34.at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
35.at java.io.BufferedInputStream.read(BufferedInputStream.java:313)
36.at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:606)
37.at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:554)
38.at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:940)
39.at com.Test.main(Test.java:52)
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还行,用在项目中还是不够完善。自己写了一个例子,有不完善之处,欢迎大家指正。
需要注意的地方:有三个方面
如何控制超时机制
如何处理异常
如何处理请求错误的
Java代码
1.private class XmlAsyncLoader extends XmlResourceRequest {
2.
3. private boolean mIsCancle = false;
4. private HttpGet mGet;
5. private HttpClient mHttp;
6.
7. public XmlAsyncLoader(MxActivity<?> activity, String url)
8. throws MalformedURLException {
9. super(activity, url);
10. }
11.
12. @Override
13. protected void doTaskInBackground() {
14. // 请求数据
15. if (mUrl.toLowerCase().startsWith("http://")) {
16. mGet = initHttpGet(mUrl);
17. mHttp = initHttp();
18. try {
19. HttpResponse response = mHttp.execute(mGet);
20. if (mIsCancle) {
21. return;
22. }
23. if (response != null) {
24. if(response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){
25. onResponseError("network error");
26. Log.v(TAG, "the code is :"+response.getStatusLine().getStatusCode());
27. return;
28. }
29. notifyUpdateProgress(70);
30. Document doc = getDocumet(response);
31. Element root = doc.getDocumentElement();
32. NodeList appList = root
33. .getElementsByTagName(Item_ELEMENT_NAME);
34. final int len = appList.getLength();
35. if (len <= 0) {// 没有items
36. onFoundNoItems();
37. return;
38. }
39. for (int i = 0; i < len; i++) {
40. Element item = (Element) appList.item(i);
41. if (item.getNodeType() == Node.ELEMENT_NODE) {
42. HahaItemInfo info = createHahaItemIno(item);
43. if (mIsCancle){
44. return;
45. }
46. onFoundItem(info, 80 + 20 * (i + 1) / len);
47. addUrlToQueue(info.userIconUrl);
48. }
49. };
50.
51. }
52. }catch(ConnectTimeoutException e){
53. onResponseError("time out");
54. } catch (ClientProtocolException e) {
55. --mCurrentPage;
56. e.printStackTrace();
57. } catch (IOException e) {
58. --mCurrentPage;
59. e.printStackTrace();
60. } catch (XmlPullParserException e) {
61. --mCurrentPage;
62. e.printStackTrace();
63. }finally{
64. notifyLoadFinish();
65. notifyLoadImages();
66. mHttp.getConnectionManager().shutdown();
67. }
68.
69. }
70. }
71.
72.
73. private HttpClient initHttp() {
74. HttpClient client = new DefaultHttpClient();
75. client.getParams().setIntParameter(
76. HttpConnectionParams.SO_TIMEOUT, TIME_OUT_DELAY); // 超时设置
77. client.getParams().setIntParameter(
78. HttpConnectionParams.CONNECTION_TIMEOUT, TIME_OUT_DELAY);// 连接超时
79. return client;
80. }
81.
82. private HttpGet initHttpGet(String mUrl) {
83. HttpGet get = new HttpGet(mUrl);
84. initHeader(get);
85. return get;
86. }
87.
88.
89. @Override
90. public boolean tryCancel() {
91. Log.i(TAG, "tryCanle is working");
92. mGet.abort();
93. mIsCancle = true;
94. mHttp.getConnectionManager().shutdown();
95. notifyLoadFinish();
96. return true;
97. }
98.
99. }
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关键字
不管是请求成功,还是失败,都需要关闭链接。
作者:
如果有一天21
时间:
2012-01-12 10:22
谢谢分享
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2