安卓开发-HttpClient使用



http://blog.csdn.net/zhangfei_jiayou/article/details/20797255

http://blog.csdn.net/zhangfei_jiayou/article/details/20797255

http://blog.csdn.net/zhangfei_jiayou/article/details/20797255

http://blog.csdn.net/zhangfei_jiayou/article/details/20797255

http://blog.csdn.net/zhangfei_jiayou/article/details/20797255



 

Android--Apache HttpClient

分类: android java   47人阅读  评论(0)  收藏  举报

HttpClient是Apache开源组织提供的一个开源的项目,从名字上就可以看出,它是一个简单的HTTP客户端(并不是浏览器),可以发送HTTP请求,接受HTTP响应。但是不会缓存服务器的响应,不能执行HTTP页面中签入嵌入的JS代码,自然也不会对页面内容进行任何解析、处理,这些都是需要开发人员来完成的。

  现在Android已经成功集成了HttpClient,所以开发人员在Android项目中可以直接使用HttpClient来想Web站点提交请求以及接受响应,如果使用其他的Java项目,需要引入进相应的Jar包。HttpClient可以在官网上下载

  

HttpClient

  HttpClient其实是一个interface类型,HttpClient封装了对象需要执行的Http请求、身份验证、连接管理和其它特性。从文档上看,HttpClient有三个已知的实现类分别是:AbstractHttpClient, AndroidHttpClient, DefaultHttpClient,会发现有一个专门为Android应用准备的实现类AndroidHttpClient,当然使用常规的DefaultHttpClient也可以实现功能,但是既然开发的是Android应用程序,还是使用Android专有的实现类,一定有其优势。

  从两个类包所有在位置就可以看出区别,AndroidHttpClient定义在android.net.http.AndroidHttpClient包下,属于Android原生的http访问,而DefaultHttpClient定义在org.apache.http.impl.client.DefaultHttpClient包下,属于对apche项目的支持。而AndroidHttpClient没有公开的构造函数,只能通过静态方法newInstance()方法来获得AndroidHttpClient对象。

  AndroidHttpClient对于DefaultHttpClient做了一些改进,使其更使用用于Android项目:

  1. 关掉过期检查,自连接可以打破所有的时间限制。
  2. 可以设置ConnectionTimeOut(连接超时)和SoTimeout(读取数据超时)。
  3. 关掉重定向。
  4. 使用一个Session缓冲用于SSL Sockets。
  5. 如果服务器支持,使用gzip压缩方式用于在服务端和客户端传递的数据。
  6. 默认情况下不保留Cookie。    

  简单来说,用HttpClient发送请求、接收响应都很简单,只需要几个步骤即可:

  1. 创建HttpClient对象。
  2. 创建对应的发送请求的对象,如果需要发送GET请求,则创建HttpGet对象,如果需要发送POST请求,则创建HttpPost对象。
  3. 对于发送请求的参数,GET和POST使用的方式不同,GET方式可以使用拼接字符串的方式,把参数拼接在URL结尾;POST方式需要使用setEntity(HttpEntity entity)方法来设置请求参数。
  4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,执行该方法返回一个HttpResponse对象。
  5. 调用HttpResponse的对应方法获取服务器的响应头、响应内容等。

DefaultHttpClient

  先看看使用DefaultHttpClient方式发送Web站点请求,上面已经简要说明了步骤,在这里简要说明一个参数的传递问题,对于GET方式,只需要拼接字符串就在URL结尾即可,但是对于POST方式,需要传递HttpEntity对象,HttpEntity为一个接口,有多个实现类,可以使用其间接子继承,UrlEncodedFormEntity类来保存请求参数,并传递给HttpPost。

  此例子简单实现了在Android客户端使用DefaultHttpClient实现一个Http站点登陆的实现,使用的是POST传递,其传递值只需要传递username+password即可,当传递的数据为admin+123则认为登陆成功。Web站点使用.net的架构,一个一般处理程序,简单的比对账户密码,这里就不在此讲解。

  因为Android4.0之后对使用网络有特殊要求,已经无法再在主线程中访问网络了,必须使用多线程访问的模式,其他的一些信息在代码注释中已经说明。

 DefaultHttpClient-Code

复制代码
  1 package com.bgxt.httpUtils;
  2 
  3 import java.io.ByteArrayOutputStream;
  4 import java.io.IOException;
  5 import java.io.InputStream;
  6 import java.io.UnsupportedEncodingException;
  7 import java.util.ArrayList;
  8 import java.util.HashMap;
  9 import java.util.List;
 10 import java.util.Map;
 11 
 12 import org.apache.http.HttpResponse;
 13 import org.apache.http.NameValuePair;
 14 import org.apache.http.client.ClientProtocolException;
 15 import org.apache.http.client.entity.UrlEncodedFormEntity;
 16 import org.apache.http.client.methods.HttpPost;
 17 import org.apache.http.impl.client.DefaultHttpClient;
 18 import org.apache.http.message.BasicNameValuePair;
 19 
 20 public class httpClientUtils implements Runnable {
 21     /**
 22      * 对于Android4.0之上的环境下,不能在主线程中访问网络 所以这里另新建了一个实现了Runnable接口的Http访问类
 23      */
 24     private String username;
 25     private String password;
 26 
 27     public httpClientUtils(String username, String password) {
 28         // 初始化用户名和密码
 29         this.username = username;
 30         this.password = password;
 31     }
 32 
 33     @Override
 34     public void run() {
 35         // 设置访问的Web站点
 36         String path = "http://192.168.1.103:1231/loginas.ashx";
 37         // 设置Http请求参数
 38         Map<String, String> params = new HashMap<String, String>();
 39         params.put("username", username);
 40         params.put("password", password);
 41 
 42         String result = sendHttpClientPost(path, params, "utf-8");
 43         // 把返回的接口输出
 44         System.out.println(result);
 45     }
 46 
 47     /**
 48      * 发送Http请求到Web站点
 49      * 
 50      * @param path
 51      *            Web站点请求地址
 52      * @param map
 53      *            Http请求参数
 54      * @param encode
 55      *            编码格式
 56      * @return Web站点响应的字符串
 57      */
 58     private String sendHttpClientPost(String path, Map<String, String> map,
 59             String encode) {
 60         List<NameValuePair> list = new ArrayList<NameValuePair>();
 61         if (map != null && !map.isEmpty()) {
 62             for (Map.Entry<String, String> entry : map.entrySet()) {
 63                 // 解析Map传递的参数,使用一个键值对对象BasicNameValuePair保存。
 64                 list.add(new BasicNameValuePair(entry.getKey(), entry
 65                         .getValue()));
 66             }
 67         }
 68         try {
 69             // 实现将请求 的参数封装封装到HttpEntity中。
 70             UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, encode);
 71             // 使用HttpPost请求方式
 72             HttpPost httpPost = new HttpPost(path);
 73             // 设置请求参数到Form中。
 74             httpPost.setEntity(entity);
 75             // 实例化一个默认的Http客户端
 76             DefaultHttpClient client = new DefaultHttpClient();
 77             // 执行请求,并获得响应数据
 78             HttpResponse httpResponse = client.execute(httpPost);
 79             // 判断是否请求成功,为200时表示成功,其他均问有问题。
 80             if (httpResponse.getStatusLine().getStatusCode() == 200) {
 81                 // 通过HttpEntity获得响应流
 82                 InputStream inputStream = httpResponse.getEntity().getContent();
 83                 return changeInputStream(inputStream, encode);
 84             }
 85         } catch (UnsupportedEncodingException e) {
 86             e.printStackTrace();
 87         } catch (ClientProtocolException e) {
 88             e.printStackTrace();
 89         } catch (IOException e) {
 90             e.printStackTrace();
 91         }
 92         return "";
 93     }
 94 
 95     /**
 96      * 把Web站点返回的响应流转换为字符串格式
 97      * 
 98      * @param inputStream
 99      *            响应流
100      * @param encode
101      *            编码格式
102      * @return 转换后的字符串
103      */
104     private String changeInputStream(InputStream inputStream, String encode) {
105         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
106         byte[] data = new byte[1024];
107         int len = 0;
108         String result = "";
109         if (inputStream != null) {
110             try {
111                 while ((len = inputStream.read(data)) != -1) {
112                     outputStream.write(data, 0, len);
113                 }
114                 result = new String(outputStream.toByteArray(), encode);
115 
116             } catch (IOException e) {
117                 e.printStackTrace();
118             }
119         }
120         return result;
121     }
122 
123 }
复制代码

AndroidHttpClient

  使用AndroidHttpClient的方式和DefaultHttpClient差不多,不多的几点区别上面已经说明,但是在此例子中没有体现。有一点需要注意的是,AndroidHttpClient是一个final类,也没有公开的构造函数,所以无法使用new的形式对其进行实例化,必须使用AndroidHttpClient.newInstance()方法获得AndroidHttpClient对象。

  示例中依然是使用POST请求,实现的功能和DefaultHttpClient示例一样。细节部分已经在注释中体现,直接看代码即可。

复制代码
  1 package com.bgxt.httpUtils;
  2 
  3 import java.io.ByteArrayOutputStream;
  4 import java.io.IOException;
  5 import java.io.InputStream;
  6 import java.io.UnsupportedEncodingException;
  7 import java.util.ArrayList;
  8 import java.util.HashMap;
  9 import java.util.List;
 10 import java.util.Map;
 11 
 12 import org.apache.http.HttpResponse;
 13 import org.apache.http.NameValuePair;
 14 import org.apache.http.client.ClientProtocolException;
 15 import org.apache.http.client.HttpClient;
 16 import org.apache.http.client.entity.UrlEncodedFormEntity;
 17 import org.apache.http.client.methods.HttpPost;
 18 import org.apache.http.impl.client.DefaultHttpClient;
 19 import org.apache.http.message.BasicNameValuePair;
 20 
 21 import android.net.http.AndroidHttpClient;
 22 
 23 public class AndroidHttpClientUtils implements Runnable {
 24 
 25     private String username;
 26     private String password;
 27 
 28     public AndroidHttpClientUtils(String username, String password) {
 29         // 初始化用户名和密码
 30         this.username = username;
 31         this.password = password;
 32     }
 33 
 34     @Override
 35     public void run() {
 36         // 设置访问的Web站点
 37         String path = "http://192.168.1.103:1231/loginas.ashx";
 38         //设置Http请求参数
 39         Map<String, String> params = new HashMap<String, String>();
 40         params.put("username", username);
 41         params.put("password", password);
 42 
 43         String result = sendHttpClientPost(path, params, "utf-8");
 44         //把返回的接口输出
 45         System.out.println(result);
 46     }
 47     /**
 48      * 发送Http请求到Web站点
 49      * @param path Web站点请求地址
 50      * @param map Http请求参数
 51      * @param encode 编码格式
 52      * @return Web站点响应的字符串
 53      */
 54     private String sendHttpClientPost(String path,Map<String, String> map,String encode)
 55     {
 56         List<NameValuePair> list=new ArrayList<NameValuePair>();
 57         if(map!=null&&!map.isEmpty())
 58         {
 59             for(Map.Entry<String, String> entry:map.entrySet())
 60             {
 61                 //解析Map传递的参数,使用一个键值对对象BasicNameValuePair保存。
 62                 list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
 63             }
 64         }
 65         try {
 66             //实现将请求 的参数封装封装到HttpEntity中。
 67             UrlEncodedFormEntity entity=new UrlEncodedFormEntity(list, encode);
 68             //使用HttpPost请求方式
 69             HttpPost httpPost=new HttpPost(path);
 70             //设置请求参数到Form中。
 71             httpPost.setEntity(entity);
 72             //实例化一个默认的Http客户端,使用的是AndroidHttpClient
 73             HttpClient client=AndroidHttpClient.newInstance("");
 74             //执行请求,并获得响应数据
 75             HttpResponse httpResponse= client.execute(httpPost);
 76             //判断是否请求成功,为200时表示成功,其他均问有问题。
 77             if(httpResponse.getStatusLine().getStatusCode()==200)
 78             {
 79                 //通过HttpEntity获得响应流
 80                 InputStream inputStream=httpResponse.getEntity().getContent();
 81                 return changeInputStream(inputStream,encode);
 82             }
 83             
 84         } catch (UnsupportedEncodingException e) {
 85             // TODO Auto-generated catch block
 86             e.printStackTrace();
 87         } catch (ClientProtocolException e) {
 88             // TODO Auto-generated catch block
 89             e.printStackTrace();
 90         } catch (IOException e) {
 91             // TODO Auto-generated catch block
 92             e.printStackTrace();
 93         }
 94         
 95         return "";
 96     }                    
 97     /**
 98      * 把Web站点返回的响应流转换为字符串格式
 99      * @param inputStream 响应流
100      * @param encode 编码格式
101      * @return 转换后的字符串
102      */
103     private  String changeInputStream(InputStream inputStream,
104             String encode) { 
105         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
106         byte[] data = new byte[1024];
107         int len = 0;
108         String result="";
109         if (inputStream != null) {
110             try {
111                 while ((len = inputStream.read(data)) != -1) {
112                     outputStream.write(data,0,len);                    
113                 }
114                 result=new String(outputStream.toByteArray(),encode);
115                 
116             } catch (IOException e) {
117                 e.printStackTrace();
118             }
119         }
120         return result;
121     }
122 }
复制代码

  在本文的示例中,环境是使用的Android项目,可以对其进行简单的界面布局,如图:

  如果输入用户和密码为:admin+123,则可以再LogCat中查看到登录成功。

  源码下载

 

总结

  最近的两次博客中,已经分别介绍了HttpUrlConnection和HttpClient两种方式,通过Http协议对Web站点的访问。如果还不了解HttpURLConnection的读者,可以看看Android--Http协议

  根据官方文档上说的显示,Android包括两个Http客户端:HttpURLConnection和Apache HttpClient。并且都支持HTTPS,流媒体上传下载,并且可配置超时以及支持IPv6和连接池技术。但是因为移动设备的局限性,HttpURLConnection会是比Apache Http更好的选择,因为其API简单,运行消耗内存小,并且具有公开化的压缩算法,以及响应缓存,能更好的减少网络使用,提供运行速度和节省电池。

  但是也不能否认Apache HttpClient,它有大量的灵活的API,实现比较稳定,少有Bug,可造成的问题就是很难在不影响其兼容性的情况下对其进行改进了。现在Android开发者已经慢慢放弃Apache HttpClient的使用,转而使用HttpURLConnection。但是对于Android2.2之前的版本,HttpURLConnection具有一个致命的BUG,在响应输入流InputStream中调用.Close()方法将会阻碍连接池,因为这个BUG,只能放弃连接池的使用,但是Apache HttpClient不存在这个问题,当然Android2.3之后的版本中,HttpURLConnection已经解决了这个BUG,可以放心使用。

转载至:http://www.cnblogs.com/plokmju/p/Android_apacheHttpClient.html

























http://blog.csdn.net/zhangfei_jiayou/article/details/8076215

http://blog.csdn.net/zhangfei_jiayou/article/details/8076215

http://blog.csdn.net/zhangfei_jiayou/article/details/8076215



基于Apache的HttpClient进行HTTP网络访问

分类: java android   815人阅读  评论(0)  收藏  举报
在Android中,除了使用java.net包下的API访问HTTP服务之外,我们还可以换一种途径去完成工作.Android SDK附带了Apache的HttpClient API.Apache HttpClient是一个完善的HTTP客户端,它提供了对HTTP协议的全面支持,可以使用HTTP GET和POST进行访问.下面我们就结合实例,介绍一下HttpClient的使用方法:
[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3. package=""  
  4. android:versionCode="1"  
  5. android:versionName="1.0">  
  6. <application android:icon="@drawable/icon" android:label="@string/app_name">  
  7. <!-- 配置测试要使用的类库 -->  
  8. <uses-library android:name="android.test.runner"/>  
  9. </application>  
  10. <!-- 配置测试设备的主类和目标包 -->  
  11. <instrumentation android:name="android.test.InstrumentationTestRunner"  
  12. android:targetPackage="com.scott.http"/>  
  13. <!-- 访问HTTP服务所需的网络权限 -->  
  14. <uses-permission android:name="android.permission.INTERNET"/>  
  15. <uses-sdk android:minSdkVersion="8" />  
  16. </manifest>  

然后,我们的单元测试类需要继承android.test.AndroidTestCase类,这个类本身是继承junit.framework.TestCase,并提供了getContext()方法,用于获取Android上下文环境,这个设计非常有用,因为很多Android API都是需要Context才能完成的.

现在让我们来看一下我们的测试用例,HttpTest.java代码如下:

[java]  view plain copy
  1. public class HttpTest extends AndroidTestCase {  
  2.     private static final String PATH = "http://192.168.1.57:8080/web";  
  3.   
  4.     public void testGet() throws Exception {  
  5.         HttpClient client = new DefaultHttpClient();  
  6.         HttpGet get = new HttpGet(PATH  
  7.                 + "/TestServlet?id=1001&name=john&age=60");  
  8.         HttpResponse response = client.execute(get);  
  9.         if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {  
  10.             InputStream is = response.getEntity().getContent();  
  11.             String result = inStream2String(is);  
  12.             Assert.assertEquals(result, "GET_SUCCESS");  
  13.         }  
  14.     }  
  15.   
  16.     public void testPost() throws Exception {  
  17.         HttpClient client = new DefaultHttpClient();  
  18.         HttpPost post = new HttpPost(PATH + "/TestServlet");  
  19.         List<NameValuePair> params = new ArrayList<NameValuePair>();  
  20.         params.add(new BasicNameValuePair("id""1001"));  
  21.         params.add(new BasicNameValuePair("name""john"));  
  22.         params.add(new BasicNameValuePair("age""60"));  
  23.         HttpEntity formEntity = new UrlEncodedFormEntity(params);  
  24.         post.setEntity(formEntity);  
  25.         HttpResponse response = client.execute(post);  
  26.         if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {  
  27.             InputStream is = response.getEntity().getContent();  
  28.             String result = inStream2String(is);  
  29.             Assert.assertEquals(result, "POST_SUCCESS");  
  30.         }  
  31.     }  
  32.   
  33.     public void testUpload() throws Exception {  
  34.         InputStream is = getContext().getAssets().open("books.xml");  
  35.         HttpClient client = new DefaultHttpClient();  
  36.         HttpPost post = new HttpPost(PATH + "/UploadServlet");  
  37.         InputStreamBody isb = new InputStreamBody(is, "books.xml");  
  38.         MultipartEntity multipartEntity = new MultipartEntity();  
  39.         multipartEntity.addPart("file", isb);  
  40.         multipartEntity.addPart("desc"new StringBody("this is description."));  
  41.         post.setEntity(multipartEntity);  
  42.         HttpResponse response = client.execute(post);  
  43.         if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {  
  44.             is = response.getEntity().getContent();  
  45.             String result = inStream2String(is);  
  46.             Assert.assertEquals(result, "UPLOAD_SUCCESS");  
  47.         }  
  48.     }  
  49.   
  50.     // 将输入流转换成字符串  
  51.     private String inStream2String(InputStream is) throws Exception {  
  52.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  53.         byte[] buf = new byte[1024];  
  54.         int len = -1;  
  55.         while ((len = is.read(buf)) != -1) {  
  56.             baos.write(buf, 0, len);  
  57.         }  
  58.         return new String(baos.toByteArray());  
  59.     }  
  60. }  
因为此文件包含三个测试用例,所以我将会逐个介绍一下.
首先,需要注意的是,我们定位服务器地址时使用到了IP,因为这里不能用localhost,服务端是在windows上运行,而本单元测试运行在Android平台,如果使用localhost就意味着在Android内部去访问服务,可能是访问不到的,所以必须用IP来定位服务.
我们先来分析一下testGet测试用例.我们使用了HttpGet,请求参数直接附在URL后面,然后由HttpClient执行GET请求,如果响应成功的话,取得响应内如输入流,并转换成字符串,最后判断是否为GET_SUCCESS.
testGet测试对应服务端Servlet代码如下:

[java]  view plain copy
  1. @Override  
  2. protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {  
  3.         System.out.println("doGet method is called.");  
  4.     String id = request.getParameter("id");  
  5.     String name = request.getParameter("name");  
  6.     String age = request.getParameter("age");  
  7.     System.out.println("id:" + id + ", name:" + name + ", age:" + age);  
  8.     response.getWriter().write("GET_SUCCESS");  
  9. }  
然后再说testPost测试用例。我们使用了HttpPost,URL后面并没有附带参数信息,参数信息被包装成一个由NameValuePair类型组成的集合的形式,然后经过UrlEncodedFormEntity处理后调用HttpPost的setEntity方法进行参数设置,最后由HttpClient执行。
testPost测试对应的服务端代码如下:

[java]  view plain copy
  1. @Override  
  2. protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {  
  3.     System.out.println("doPost method is called.");  
  4.     String id = request.getParameter("id");  
  5.     String name = request.getParameter("name");  
  6.     String age = request.getParameter("age");  
  7.     System.out.println("id:" + id + ", name:" + name + ", age:" + age);  
  8.     response.getWriter().write("POST_SUCCESS");  
  9. }  
上面两个是最基本的GET请求和POST请求,参数都是文本数据类型,能满足普通的需求,不过在有的场合例如我们要用到上传文件的时候,就不能使用基本的GET请求和POST请求了,我们要使用多部件的POST请求。下面介绍一下如何使用多部件POST操作上传一个文件到服务端。
由于Android附带的HttpClient版本暂不支持多部件POST请求,所以我们需要用到一个HttpMime开源项目,该组件是专门处理与MIME类型有关的操作。因为HttpMime是包含在HttpComponents 项目中的,所以我们需要去apache官方网站下载HttpComponents,然后把其中的HttpMime.jar包放到项目中去。
然后,我们观察testUpload测试用例,我们用HttpMime提供的InputStreamBody处理文件流参数,用StringBody处理普通文本参数,最后把所有类型参数都加入到一个MultipartEntity的实例中,并将这个multipartEntity设置为此次POST请求的参数实体,然后执行POST请求。服务端Servlet代码如下:

[java]  view plain copy
  1. @SuppressWarnings("serial")  
  2. public class UploadServlet extends HttpServlet {  
  3.     @Override  
  4.     @SuppressWarnings("rawtypes")  
  5.     protected void doPost(HttpServletRequest request,  
  6.             HttpServletResponse response) throws ServletException, IOException {  
  7.         boolean isMultipart = ServletFileUpload.isMultipartContent(request);  
  8.         if (isMultipart) {  
  9.             FileItemFactory factory = new DiskFileItemFactory();  
  10.             ServletFileUpload upload = new ServletFileUpload(factory);  
  11.             try {  
  12.                 List items = upload.parseRequest(request);  
  13.                 Iterator iter = items.iterator();  
  14.                 while (iter.hasNext()) {  
  15.                     FileItem item = (FileItem) iter.next();  
  16.                     if (item.isFormField()) {  
  17.                         // 普通文本信息处理  
  18.                         String paramName = item.getFieldName();  
  19.                         String paramValue = item.getString();  
  20.                         System.out.println(paramName + ":" + paramValue);  
  21.                     } else {  
  22.                         // 上传文件信息处理  
  23.                         String fileName = item.getName();  
  24.                         byte[] data = item.get();  
  25.                         String filePath = getServletContext().getRealPath(  
  26.                                 "/files")  
  27.                                 + "/" + fileName;  
  28.                         FileOutputStream fos = new FileOutputStream(filePath);  
  29.                         fos.write(data);  
  30.                         fos.close();  
  31.                     }  
  32.                 }  
  33.             } catch (FileUploadException e) {  
  34.                 e.printStackTrace();  
  35.             }  
  36.         }  
  37.         response.getWriter().write("UPLOAD_SUCCESS");  
  38.     }  
  39. }  
服务端使用apache开源项目FileUpload进行处理,所以我们需要commons-fileupload和commons-io这两个项目的jar包。
介绍完上面的三种不同的情况之后,我们需要考虑一个问题,在实际应用中,我们不能每次都新建HttpClient,而是应该只为整个应用创建一个HttpClient,并将其用于所有HTTP通信.此外,还应该注意在通过一个HttpClient同时发出多个请求时可能发生的多线程问题.针对这两个问题,我们需要改进一下我们的项目:
1.扩展系统默认的Application,并应用在项目中。
2.使用HttpClient类库提供的ThreadSafeClientManager来创建和管理HttpClient。
其中MyApplication扩展了系统的Application,代码如下:

[java]  view plain copy
  1. public class MyApplication extends Application {  
  2.     private HttpClient httpClient;  
  3.   
  4.     @Override  
  5.     public void onCreate() {  
  6.         super.onCreate();  
  7.         httpClient = this.createHttpClient();  
  8.     }  
  9.   
  10.     @Override  
  11.     public void onLowMemory() {  
  12.         super.onLowMemory();  
  13.         this.shutdownHttpClient();  
  14.     }  
  15.   
  16.     @Override  
  17.     public void onTerminate() {  
  18.         super.onTerminate();  
  19.         this.shutdownHttpClient();  
  20.     }  
  21.   
  22.     // 创建HttpClient实例  
  23.     private HttpClient createHttpClient() {  
  24.         HttpParams params = new BasicHttpParams();  
  25.         HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);  
  26.         HttpProtocolParams.setContentCharset(params,  
  27.                 HTTP.DEFAULT_CONTENT_CHARSET);  
  28.         HttpProtocolParams.setUseExpectContinue(params, true);  
  29.         SchemeRegistry schReg = new SchemeRegistry();  
  30.         schReg.register(new Scheme("http", PlainSocketFactory  
  31.                 .getSocketFactory(), 80));  
  32.         schReg.register(new Scheme("https",  
  33.                 SSLSocketFactory.getSocketFactory(), 443));  
  34.         ClientConnectionManager connMgr = new ThreadSafeClientConnManager(  
  35.                 params, schReg);  
  36.         return new DefaultHttpClient(connMgr, params);  
  37.     }  
  38.   
  39.     // 关闭连接管理器并释放资源  
  40.     private void shutdownHttpClient() {  
  41.         if (httpClient != null && httpClient.getConnectionManager() != null) {  
  42.             httpClient.getConnectionManager().shutdown();  
  43.         }  
  44.     }  
  45.   
  46.     // 对外提供HttpClient实例  
  47.     public HttpClient getHttpClient() {  
  48.         return httpClient;  
  49.     }  
  50. }  
我们重写了onCreate()方法,在系统启动时就创建一个HttpClient;重写了onLowMemory()和onTerminate()方法,在内存不足和应用结束时关闭连接,释放资源.需要注意的是,当实例化DefaultHttpClient时,传入一个由ThreadSafeClientConnManager创建的一个ClientConnectionManager实例,负责管理HttpClient的HTTP连接.

然后,想要让我们这个加强版的“Application”生效,需要在AndroidManifest.xml中做如下配置:

[html]  view plain copy
  1. <application android:name=".MyApplication" ...>  
  2. ....  
  3. </application>  
如果我们没有配置,系统默认会使用android.app.Application,我们添加了配置,系统就会使用我们的com.scott.http.MyApplication,然后就可以在context中调用getApplication()来获取MyApplication实例.
有了上面的配置,我们就可以在活动中应用了,HttpActivity.java代码如下:

[java]  view plain copy
  1. public class HttpActivity extends Activity {  
  2.     @Override  
  3.     protected void onCreate(Bundle savedInstanceState) {  
  4.         super.onCreate(savedInstanceState);  
  5.         setContentView(R.layout.main);  
  6.         Button btn = (Button) findViewById(R.id.btn);  
  7.         btn.setOnClickListener(new View.OnClickListener() {  
  8.             @Override  
  9.             public void onClick(View v) {  
  10.                 execute();  
  11.             }  
  12.         });  
  13.     }  
  14.   
  15.     private void execute() {  
  16.         try {  
  17.             MyApplication app = (MyApplication) this.getApplication(); // 获取MyApplication实例  
  18.             HttpClient client = app.getHttpClient(); // 获取HttpClient实例  
  19.             HttpGet get = new HttpGet(  
  20.                     "http://192.168.1.57:8080/web/TestServlet?id=1001&name=john&age=60");  
  21.             HttpResponse response = client.execute(get);  
  22.             if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {  
  23.                 InputStream is = response.getEntity().getContent();  
  24.                 String result = inStream2String(is);  
  25.                 Toast.makeText(this, result, Toast.LENGTH_LONG).show();  
  26.             }  
  27.         } catch (Exception e) {  
  28.             e.printStackTrace();  
  29.         }  
  30.     }  
  31.   
  32.     // 将输入流转换成字符串  
  33.     private String inStream2String(InputStream is) throws Exception {  
  34.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  35.         byte[] buf = new byte[1024];  
  36.         int len = -1;  
  37.         while ((len = is.read(buf)) != -1) {  
  38.             baos.write(buf, 0, len);  
  39.         }  
  40.         return new String(baos.toByteArray());  
  41.     }  
  42. }  




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值