前面几篇博文简单的介绍了一些常见的Http的操作,这些操作几乎都是在新开的线程中进行的网络请求,并在日志中打印出获取到的网络数据。那么,问题来了!(呃~感觉下一句是蓝翔有木有?)如何在把获取到的网络数据显示在UI界面上呢?如果按照前几篇博文的例子,并在主线程中直接对子线程获取的网络数据直接进行操作就会发现一个问题,那就是在主线程中根本就获取不到子线程得到的从服务器返回的数据。因为,网络操作属于耗时操作,为了不阻塞主线程而放在子线程中,当主线程中的代码执行完后子线程未必就获取到服务器返回的数据了。所以,为了解决这样的问题我们通常在Http的操作中加上异步消息机制,并且为了简化操作对其进行简单的封装,加上回调机制。

这篇博文就以HttpClient访问百度首页为例子,对之前博文中的Http操作进一步的完善。

首先,先回忆一下使用HttpClient的最简单的步骤或者说是过程:

(这里的strurl为"http://www.baidu.com",str为从服务器返回的数据。)

HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(strurl);
HttpResponse response= client.execute(request);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String str = EntityUtils.toString(response.getEntity());
}

下面将基于上面的这些操作来实现简易封装:

首先加入回调机制:

(如果对回调还不太熟悉,请参考博文《java回调机制解析》)

public interface HttpCallback {void onSuccess(Object result);void onFailure(Exception result);}

接下来,实现一个Request类:

这个类一共有三个属性:

method是在该类中用enum类型限定的RequestMethod类型的对象,用于设置请求方式。

url就是网络请求的路径。

callback为回调接口对象,用于在网络请求中获取到数据后将数据传递至调用处。

public class Request {public RequestMethod method;public String url;public HttpCallback callback;public Request(String url, RequestMethod method) {this.method = method;this.url = url;}public Request(String url) {this.method = RequestMethod.GET;this.url = url;}public enum RequestMethod {GET, POST, DELETE, PUT}public void setCallBack(HttpCallback callback) {this.callback = callback;}public void execute() {RequstTask task = new RequstTask(this);task.execute();}}

从上面的代码可以看出,该类的两个构造函数,都需要传入URL,其中一个构造函数可以设置请求方式,另一个设置默认请求方式GET。
在该类中有一个execute()方法,在这个方法中RequestTask类继承于AsyncTask,它的作用就是在RequestTask中进行网络请求。

RequestTask代码如下:

public class RequstTask extends AsyncTask<Void, integer, Object> {private Request requset;public RequstTask(Request requset) {this.requset = requset;}@Overrideprotected void onPreExecute() {// TODO Auto-generated method stubsuper.onPreExecute();}@Overrideprotected Object doInBackground(Void... params) {try {HttpResponse response = HttpClientUtils.execute(requset);if (requset.callback != null) {//如果进一步抽象化回调接口,使其子抽象类能分别处理多种格式的数据(如:JSON、XML、String、File),可以更方便//这里直接使用返回String类型的数据if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){return EntityUtils.toString(response.getEntity());}return "请求失败";} else {return null;}} catch (Exception e) {return e;}}@Overrideprotected void onPostExecute(Object result) {if (requset.callback != null) {if (result instanceof Exception) {requset.callback.onFailure((Exception) result);} else {requset.callback.onSuccess(result);}}}@Overrideprotected void onProgressUpdate(integer... values) {// TODO Auto-generated method stubsuper.onProgressUpdate(values);}}

这个类的构造函数需要传递一个Request对象,会根据这个Request对象的method属性确定请求方式、url属性确定请求路径,根据callback属性的有无来判断是否是否将获取到的网络数据传递至调用接口处。
在doInBackground()中如果Request对象的callback属性为null则返回null:

当Request对象的callback属性不为null,则先取出服务器返回的状态码(这里的response为服务器返回的信息),如果等于200(也就是HttpStatus.SC_OK)那么就说明响应成功了。再调用getEntity()方法获取到一个HttpEntity实例,然后再用EntityUtils.toString()这个静态方法将HttpEntity转换成字符串并return。返回后的数据将传入onPostExecute()方法中作为参数。

      if (requset.callback != null) {//如果进一步抽象化回调接口,使其子抽象类能分别处理多种格式的数据(如:JSON、XML、String、File),可以更方便//这里直接使用返回String类型的数据if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){return EntityUtils.toString(response.getEntity());}return "请求失败";} else {return null;}

在onPostExecute()中Request对象的callback属性为null根本就没返回。反之,doInBackground()的结果result将会传递至回调接口的调用处:

    if (requset.callback != null) {if (result instanceof Exception) {requset.callback.onFailure((Exception) result);} else {requset.callback.onSuccess(result);}}

在doInBackground()中有一句代码:

HttpResponse response = HttpClientUtils.execute(requset);

这里的HttpClientUtils其实就是一个简单的封装,其代码如下:

public class HttpClientUtils {public static HttpResponse execute(Request requst) throws Exception {switch (requst.method) {case GET:return get(requst);}return null;}private static HttpResponse get(Request requst)throws ClientProtocolException, IOException {HttpClient client = new DefaultHttpClient();HttpGet get = new HttpGet(requst.url);HttpResponse response = client.execute(get);return response;}}

从代码中可以看出,execute()和get()方法都是static类型并且返回类型都是HttpResponse。在execute()方法中根据传入的Request对象的method属性结合switch语句执行相对应的网络请求方式,并返回从服务器获得HttpResponse类型的信息。这个信息在RequstTask类中被直接赋值使用。

大体的过程就是这样了。

最后的最后,在Activity中的使用:

public class MainActivity extends Activity {private Button btn;private TextView tv;private Request request;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);btn = (Button) findViewById(R.id.btn);tv = (TextView) findViewById(R.id.tv);request = new Request("http://www.baidu.com", RequestMethod.GET);btn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {try {request.setCallBack(new HttpCallback() {@Overridepublic void onSuccess(Object result) {tv.setText((String) result);}@Overridepublic void onFailure(Exception result) {tv.setText("请求失败");}});} catch (Exception e) {// TODO Auto-generated catch block
                    e.printStackTrace();}request.execute();}});}}

Activity的布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><Buttonandroid:id="@+id/btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="请求" /><ScrollViewandroid:id="@+id/sv"android:layout_width="match_parent"android:layout_height="wrap_content" ><TextViewandroid:id="@+id/tv"android:layout_width="fill_parent"android:layout_height="fill_parent" /></ScrollView></LinearLayout>

View Code

运行程序,效果如下:

Demo下载:http://download.csdn.net/detail/af74776/8066779

转载于:https://www.cnblogs.com/scetopcsa/p/4021196.html

Android之Http网络编程(四)相关推荐

  1. Android中的网络编程-黄俊东-专题视频课程

    Android中的网络编程-1902人已学习 课程介绍         剔除繁杂的理论,注重实践,深入浅出讲解Android中的网络编程 课程收益     每一个学员都能系统地掌握Android中的网 ...

  2. 网络编程四-原生JDK的NIO及其应用

    目录 一.NIO介绍 1.1 什么是NIO? 1.2 NIO和BIO的区别 1.3 适用场景 二.NIO的核心组成 2.1 Selector 2.2 Channels 2.3 buffer缓冲区 2. ...

  3. Linux 网络编程四(socket多线程升级版)

    //网络编程--客户端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...

  4. Unix 网络编程(四)- 典型TCP客服服务器程序开发实例及基本套接字API介绍

    转载:http://blog.csdn.net/michael_kong_nju/article/details/43457393 写在开头: 在上一节中我们学习了一些基础的用来支持网络编程的API, ...

  5. Android中的网络编程

    谷歌在Android6.0之后就废弃了使用HttpClinet进行网络连接.所以,这里需要重点学习的是通过HttpUrlConnect进行网络连接. String path="这里是你想要的 ...

  6. 网络编程(四) ———— UDP首部格式

    接上一篇博客 Java Socket(UDP/TCP 套接字) 文章目录 UDP的特点 1. 无连接 2. 不可靠 3.面向数据报 4.全双工 UDP首部格式 源端口号 (Source Port) 目 ...

  7. C#网络编程(四、Socket中英文字符大小和文本边界问题)

    转自:http://blog.csdn.net/shanyongxu/article/details/51190820,本人学习受益匪浅,楼主把重点都标记出来了,请点击链接查看原文,尊重楼主大大版权. ...

  8. Android网络编程(八) 之 HttpURLConnection原理分析

    1 使用回顾 我们在前面博文<Android网络编程(四) 之 HttpClient与HttpURLConnection>中已经对HttpURLConnection的使用进行过介绍.今天我 ...

  9. Android网络编程

    Android平台有三种网络接口可以使用,他们分别是:java.net.*(标准Java接口).Org.apache接口和Android.net.*(Android网络接口).下面分别介绍这些接口的功 ...

最新文章

  1. 这味儿上头,前有文言文,又来东北话,中文编程玩得挺得劲!
  2. different application signatures解决方法
  3. c#调用带有自定义表结构的存储过程
  4. SharePoint 2013 APP 开发示例 (六)服务端跨域访问 Web Service (REST API)
  5. 收下这12篇最新论文,炼丹不愁没灵感 | 本周值得读
  6. bootstrap配置Nacos出现Param ‘serviceName‘ is illegal, serviceName is blank
  7. 生成报告配置xml_自动化测试报告太丑?Allure拯救你!
  8. 优秀的SharePoint 2013开发工具有哪些(二)
  9. Linux 系统应用编程——进程基础
  10. 【ES】es 冻结的索引如何查询
  11. 【Hive的高级查询详】
  12. 截图截取各种右键菜单的方法
  13. 平面设计师必读的十本书
  14. 三菱FX系列PLC-编程1
  15. 使用Docker实现vsftpd配置——用户访问上传修改篇
  16. [TransactionInterceptor] [ERROR] Applicationexception overridden by rollback exception
  17. linux各文件夹作用
  18. ssl证书无效或不匹配怎么办
  19. 3dmark压力测试 linux,拷机还用Furmark? 瞧瞧3DMark压力测试怎样玩
  20. hive -- return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask

热门文章

  1. koa --- [MVC实现之三]换个角度重新开始-初始化
  2. react --- 复合组件,传递属性
  3. http --- Web页面请求的历程(如何根据URL寻找到需要的资源)
  4. Node --- Basic认证
  5. JavaScript --- 解析Cookie
  6. 25LINQ拾遗及实例
  7. 猜1-10的数字python脚本
  8. asp.net model 验证和取出 ErrorMessage 信息
  9. Reflector7及破解
  10. Hibernate5-多对1(n:1)-fetch=join