声明:本博客只是为了说明com.loopj.android.http jar包对http请求的实现方式,这个jar包是第三方封装的一个用于android开发的jar包,它是对apach的提供的一些功能的进一步的封装,所以,本博客只可以帮助你理解com.loopj.android.http jar包对http请求的实现,却不能在android基于http协议的应用开发上面给你帮助。所以,本博客的阅读对象是想了解com.loopj.android.http jar包的人,而不是需要实现android http请求的人。
在做项目过程中用到了需要通过android客户端发送http请求的问题,利用com.loopj.android.http jar包可以轻松实现。但是项目完成之后,回过头来,却对其实现的方式不甚了解。于是花了一些时间反编译了他的jar包,得到了请求的具体过程。<以发送GET请求为例>。
一、在工程中建一个控制发送请求的UpdateTask类,继承AsyncTask(为了实现请求的同步或异步发送,且防止在主线程中发送请求<android4.0以上不被允许>),重写doInBackground方法,并将请求的内容写在该方法里面。重写onPostExecute方法。
1
2
3
4
5
6
|
//请求的内容为:<br>/** * url 请求的url
* params 需要上传的参数
* responseHandler 可以传WebPage对象
* isAsync 是否异步发送请求
get(String url, RequestParams params, HttpResponseHandler responseHandler, boolean
isAsync)
|
二、每次需要发送请求时,只需要new 一个UpdateTask对象,则可以出发其回调方法,执行doInBackground方法,实现请求的发送。
三、新建一个WebPage类继承AsyncHttpResponseHandler,在WebPage里面写上请求的url,请求类型,需要上传的参数(GET请求中为Query String)。
四、目前为止,已经完成了代码的请求的发送,余下的就是get(String url, RequestParams params, HttpResponseHandler responseHandler, boolean isAsync)方法的执行,这个方法在com.loopj.android.http.AndroidHttpClient类中:
1
2
3
4
5
6
7
8
9
10
|
public void get(String url, HttpResponseHandler responseHandler, boolean
isAsync)
{
get( null , url, null , responseHandler, isAsync);
}
<span style= "color: rgb(255, 0, 0);" > /**get(null, url, null, responseHandler, isAsync)继续执行,调用下边的get方法*/ </span>
public
void get(Context context, String url, RequestParams params, HttpResponseHandler responseHandler, boolean
isAsync)
{
sendRequest( this .httpClient, this .httpContext, <span style= "color: rgb(255, 0, 0);" > new
HttpGet(getUrlWithQueryString(url, params))</span>, null ,
responseHandler, context, isAsync);
}
|
在上面的方法中又调用了3个其他的方法:
1、getUrlWithQueryString(url, params),这个方法的源码不在展示,他是用来组合url的,就是把上传的参数和原来的url组合,得到一个新的目标url,这个url请求服务器响应的内容才是我们想要的。
2、new HttpGet(getUrlWithQueryString(url, params)),这个方法的原型是 public HttpGet(String uri),在org.apache.http.client.methods.HttpGet类中,目的是生成一个请求对象。
3、sendRequest方法,这个方法仍在com.loopj.android.http.AndroidHttpClient类中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
protected
void sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, HttpResponseHandler responseHandler, Context context, boolean
isAsync)
{
if
(contentType != null ) {
uriRequest.addHeader( "Content-Type" , contentType);
}
if
(!isAsync) {
<span style= "color: rgb(255, 0, 0);" > new
AsyncHttpRequest(client, httpContext, uriRequest, responseHandler).run(); //同步时,直接发送请求。</span>
return ;
}
Future request = this .threadPool.submit(
new
AsyncHttpRequest(client, httpContext, uriRequest,
responseHandler));
if
(context != null )
{
List requestList = (List) this .requestMap.get(context);
if
(requestList == null ) {
requestList = new
LinkedList();
this .requestMap.put(context, requestList);
}
requestList.add( new
WeakReference(request));
}
}
|
这个方法比较长,但是核心就在红色标注的地方,当然,如果是异步的话,则把这个请求放入线程池中等待发送,当要发送的时候,还是要执行和同步一样的过程,在此只言同步,异步的不在赘述。
五、new AsyncHttpRequest(client, httpContext, uriRequest, responseHandler).run()方法的执行在com.loopj.android.http.AsyncHttpRequest类中。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
public <span style= "color: rgb(255, 0, 0);" >AsyncHttpRequest</span>(AbstractHttpClient client, HttpContext context, HttpUriRequest request, HttpResponseHandler responseHandler)
{
this .client = client;
this .context = context;
this .request = request;
this .responseHandler = responseHandler;
if
((responseHandler instanceof
BinaryHttpResponseHandler))
this .isBinaryRequest = true ;
}
<span style= "color: rgb(255, 0, 0);" > public
void run()</span>
{
try
{
if
( this .responseHandler != null ) {
this .responseHandler.sendStartMessage();
}
<span style= "color: rgb(255, 0, 0);" > makeRequestWithRetries();</span>
if
( this .responseHandler != null )
this .responseHandler.sendFinishMessage();
}
catch
(IOException e) {
if
( this .responseHandler != null ) {
this .responseHandler.sendFinishMessage();
if
( this .isBinaryRequest)
this .responseHandler.sendFailureMessage(e, null );
else
this .responseHandler.sendFailureMessage(e, null );
}
}
}
private
void <span style= "color: rgb(255, 0, 0);" > makeRequest()</span> throws
IOException
{
if
(!Thread.currentThread().isInterrupted()) {
<span style= "color: rgb(255, 153, 0);" >HttpResponse response = this .client.execute( this .request, this .context); //发送具体的网络请求,该方法是apach提供的<apach是在android sdk里面提供的方法<br> ,android api文档有具体的介绍在,org.apach.*中>,返回的页面信息在<span style="color: rgb(255, 153, 0);">response 里面</span>。</span>
if
((!Thread.currentThread().isInterrupted()) &&
( this .responseHandler != null ))
this .responseHandler.sendResponseMessage(response); //responseHandler 是 HttpResponseHandler对象,HttpResponseHandler全是抽象方法,需要重载。
}
}
private
void makeRequestWithRetries()
throws
ConnectException
{
boolean
retry = true ;
IOException cause = null ;
HttpRequestRetryHandler retryHandler = this .client.getHttpRequestRetryHandler();
while
(retry) {
try
{
<span style= "color: rgb(255, 0, 0);" > makeRequest();</span>
return ;
} catch
(UnknownHostException e) {
if
( this .responseHandler != null ) {
this .responseHandler.sendFailureMessage(e, "can‘t resolve host" );
}
return ;
}
catch
(SocketException e) {
if
( this .responseHandler != null ) {
this .responseHandler.sendFailureMessage(e, "can‘t resolve host" );
}
return ;
} catch
(SocketTimeoutException e) {
if
( this .responseHandler != null ) {
this .responseHandler.sendFailureMessage(e, "socket time out" );
}
return ;
} catch
(IOException e) {
cause = e;
retry = retryHandler.retryRequest(cause, ++ this .executionCount, this .context);
}
catch
(NullPointerException e)
{
cause = new
IOException( "NPE in HttpClient"
+ e.getMessage());
retry = retryHandler.retryRequest(cause, ++ this .executionCount, this .context);
}
}
ConnectException ex = new
ConnectException();
ex.initCause(cause);
throw
ex;
}
} |
六、在上面方法的执行中,如果请求发送成功,则会把返回的结果放在response中,然后通过this.responseHandler.sendResponseMessage(response)方法把信息传递出去,上面已经说了,这个方法本身是抽象的,所以必须新建一个类,实现这些方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
protected
void sendResponseMessage(HttpResponse response) {
StatusLine status = response.getStatusLine();
InputStream responseBody = null ;
try
{
responseBody = response.getEntity().getContent(); //得到response里面的主要信息,其实就是我们发送的请求对应的网页的html源码
} catch
(IOException e) {
sendFailureMessage(e, (String) null );
}
if
(status.getStatusCode() >= 300 ) {
onFailure( new
HttpResponseException(status.getStatusCode(), status.getReasonPhrase()),
responseBody);
} else
{
//对responseBody的信息,即:得到的页面源码进行你想要的处理。
}
try
{
responseBody.close();
} catch
(IOException e) {
e.printStackTrace();
}
}
|