Android之Http网络编程(四)
前面几篇博文简单的介绍了一些常见的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;
}
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
@Override
protected 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;
}
}
@Override
protected void onPostExecute(Object result) {
if (requset.callback != null) {
if (result instanceof Exception) {
requset.callback.onFailure((Exception) result);
} else {
requset.callback.onSuccess(result);
}
}
}
@Override
protected void onProgressUpdate(integer... values) {
// TODO Auto-generated method stub
super.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;
@Override
protected 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() {
@Override
public void onClick(View v) {
try {
request.setCallBack(new HttpCallback() {
@Override
public void onSuccess(Object result) {
tv.setText((String) result);
}
@Override
public 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" > <Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请求" /> <ScrollView
android:id="@+id/sv"
android:layout_width="match_parent"
android:layout_height="wrap_content" > <TextView
android:id="@+id/tv"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</ScrollView> </LinearLayout>
运行程序,效果如下:

Demo下载:http://download.csdn.net/detail/af74776/8066779
Android之Http网络编程(四)的更多相关文章
- Android之Http网络编程(三)
在前面两篇博客<Android之Http网络编程(一)>.<Android之Http网络编程(二)>中,简单的介绍了对网页的请求和客户端与服务端的简单的参数交互.那么,这一篇博 ...
- Android之Http网络编程(一)
Android应用作为一个客户端程序绝大部分都是需要进行网络请求和访问的,而http通信是一种比较常见并常用的通信方式. 在Android中http网络编程中有两种实现方式,一种是使用HttpURLC ...
- Java高并发网络编程(四)Netty
在网络应用开发的过程中,直接使用JDK提供的NIO的API,比较繁琐,而且想要进行性能提升,还需要结合多线程技术. 由于网络编程本身的复杂性,以及JDK API开发的使用难度较高,所以在开源社区中,涌 ...
- Android应用开发-网络编程(一)(重制版)
网络图片查看器 1. 确定图片的网址 2. 发送http请求 URL url = new URL(address); // 获取客户端和服务器的连接对象,此时还没有建立连接 HttpURLConnec ...
- Linux 网络编程四(socket多线程升级版)
//网络编程--客户端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...
- Linux网络编程(四)
在linux网络编程[1-3]中,我们编写的网络程序仅仅是为了了解网络编程的基本步骤,实际应用当中的网络程序并不会用那样的.首先,如果服务器需要处理高并发访问,通常不会使用linux网络编程(三)中那 ...
- Android应用开发-网络编程(一)
网络图片查看器 1. 确定图片的网址 2. 发送http请求 URL url = new URL(address); // 获取客户端和服务器的连接对象,此时还没有建立连接 HttpURLConnec ...
- Android中的网络编程
谷歌在Android6.0之后就废弃了使用HttpClinet进行网络连接.所以,这里需要重点学习的是通过HttpUrlConnect进行网络连接. String path="这里是你想要的 ...
- Android之Http网络编程(二)
上一篇文章简单的介绍了Android中http的两种通信方式,并且分别用获取百度网页做了实例.但是在实际应用中,更多的是客户端通过请求的参数来实现在服务端的具体操作,并最终返回数据给客户端.因为我们不 ...
随机推荐
- HDU-4648 Magic Pen 6 简单题
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4648 求遍前缀和,然后扫描标记下就可以了... //STATUS:C++_AC_453MS_1792K ...
- 32位Ubuntu12.04搭建Hadoop2.5.1完全分布式环境
准备工作 1.准备安装环境: 4台PC,均安装32位Ubuntu12.04操作系统,统一用户名和密码 交换机1台 网线5根,4根分别用于PC与交换机相连,1根网线连接交换机和实验室网口 2.使用ifc ...
- nyoj 199 无线网络覆盖
无线网络覆盖 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 我们的乐乐同学对于网络可算得上是情有独钟,他有一个计划,那就是用无线网覆盖郑州大学. 现在学校给了他一个 ...
- Method Swizzling 和 AOP 实践(转)
上一篇介绍了 Objective-C Messaging.利用 Objective-C 的 Runtime 特性,我们可以给语言做扩展,帮助解决项目开发中的一些设计和技术问题.这一篇,我们来探索一些利 ...
- 使用Superprg 下载 AVR/51单片机固件 【worldsing笔记】
progisp 2.0 可以下载avr.51等单片机,单击下载 Superprg 单击下载 Superprg软件志峰公司出的专用软件,配合ZF_209使用, ...
- ASP.NET- 合并HTML的表格相同项单元格
我对控件的依懒是比较少的.有几个控件我比较喜欢用,例如REPEATER显示列表的控件,能提供很大的方便. 使用REPEATER有一个比较方便的功能是通过几句代码就实现了相同项合并单元格合并,这个虽然平 ...
- DataTable 基本转换简单实例
var query = from dt in tblProduct.AsEnumerable() where dt.Field<string>("StockNo") = ...
- xcode中create groups 和 create folder reference 的区别
(文章为博主原创,未经允许,不得转载!) 今天在项目中搭建框架忽然发现工程中有黄蓝文件夹的区别,而且对应到不同的情况: 1.蓝色文件夹下文件不能被读取: 2.蓝色文件夹下创建新的文件类会直接跳过选择类 ...
- 对PostgreSQL的prepared statement的深入理解
看官方文档: http://www.postgresql.org/docs/current/static/sql-prepare.html PREPARE creates a prepared sta ...
- keystone之预备知识点
1.webobwebob是一个用来封装http request和http response的一个库,都封装成实例,方便解析http request和构建http response.最佳教程地址: ht ...