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-4605 Magic Ball Game 树状数组+离散+dfs
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4605 题意:给一颗树,每个节点有个权值w[u],每个节点只有两个儿子或者没有儿子,从根节点放下一个小球 ...
- acm-DP整理
一.背包 .各种01背包 void leastOne_Pack(int id, int num ) {//至少取一个: int i, j, c, v ; ; i <= num ; i ++ ) ...
- Use ALTER DATABASE to Move Databases
Use ALTER DATABASE to Move Databases Follow Our Daily Tips •facebook.com/TechNetTips• twitter.com/Te ...
- IOS成长之路-调用照相机和相册功能
打开相机: //先设定sourceType为相机,然后判断相机是否可用(ipod)没相机,不可用将sourceType设定为相片库 UIImagePickerControllerSourceType ...
- 松下蓄电池与UPS使用和维护
使用条件及环境1.充电电流(浮充使用):0.15CA以下2.放电电流范围:0.05CA-3CA3.环境温度:0℃-40℃ (适宜的温度是25℃) 4.充电电压:(12V电池推荐值) 周围温度 ...
- hdoj 2051 Bitset
Bitset Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- jquery foreach
<form id="input_iForm" action="${pageContext.request.contextPath}/transfer/input_s ...
- 5-17 Hashing (25分)
The task of this problem is simple: insert a sequence of distinct positive integers into a hash tabl ...
- Java Singleton 单例模式
大家可能还听过 Singleton 也就是单例模式 这个单例模式要求 在程序的运行时候 一个程序的某个类 只允许产生一个 实例 那么 这个类就是一个单例类 Java Singleton模式主要作 ...
- Codeforces Codeforces Round #319 (Div. 2) C. Vasya and Petya's Game 数学
C. Vasya and Petya's Game Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/ ...