• 利用com.loopj.android.http jar包 发送http请求过程分析<原创>


    声明:本博客只是为了说明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方法。

    //请求的内容为:
    /** * 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类中:

    public void get(String url, HttpResponseHandler responseHandler, boolean isAsync)
      {
        get(null, url, null, responseHandler, isAsync);
      }
    /**get(null, url, null, responseHandler, isAsync)继续执行,调用下边的get方法*/
      public void get(Context context, String url, RequestParams params, HttpResponseHandler responseHandler, boolean isAsync)
      {
        sendRequest(this.httpClient, this.httpContext, new HttpGet(getUrlWithQueryString(url, params)), 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类中:

    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) {
          new AsyncHttpRequest(client, httpContext, uriRequest, responseHandler).run();//同步时,直接发送请求。
          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类中。代码如下:

    public AsyncHttpRequest(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;
      }
    
      public void run()
      {
        try {
          if (this.responseHandler != null) {
            this.responseHandler.sendStartMessage();
          }
    
          makeRequestWithRetries();
    
          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 makeRequest() throws IOException
      {
        if (!Thread.currentThread().isInterrupted()) {
          HttpResponse response = this.client.execute(this.request, this.context);//发送具体的网络请求,该方法是apach提供的<apach是在android sdk里面提供的方法
             ,android api文档有具体的介绍在,org.apach.*中>,返回的页面信息在response 里面。
          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 {
            makeRequest();
            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)方法把信息传递出去,上面已经说了,这个方法本身是抽象的,所以必须新建一个类,实现这些方法。

     protected void sendResponseMessage(HttpResponse response) {
            StatusLine status = response.getStatusLine();
    //response里面有三块东西,Entity(返回url对应的内容),Locale(the status line of this response英语水平有限....),StateLine(response的状态....StatusLine.getStatusCode()可以获得状态码。)
    //这三块儿通过getEntity(),getLocale(),getStatusLine()三个方法获得。 InputStream responseBody = null; try { responseBody = response.getEntity().getContent();//得到response里面的主要信息,其实就是我们发送的请求对应的网页的html源码 } catch (IOException e) { sendFailureMessage(e, (String) null); }
    //判断状态码,大于300表示请求失败,一般是返回200. if (status.getStatusCode() >= 300) { onFailure(new HttpResponseException(status.getStatusCode(), status.getReasonPhrase()), responseBody); } else { //对responseBody的信息,即:得到的页面源码进行你想要的处理。 } try { responseBody.close(); } catch (IOException e) { e.printStackTrace(); } }
  • 相关阅读:
    我的Android app开发生涯
    极客学院
    区分H5和native页面
    H5之测试工具
    放最多水
    数组去重 快慢指针
    搜索插入位置 二分查找
    this指向
    JS 抖动和节流
    图片懒加载和预加载
  • 原文地址:https://www.cnblogs.com/yanhuofenhuang/p/3600909.html
Copyright © 2020-2023  润新知