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的两种通信方式,并且分别用获取百度网页做了实例.但是在实际应用中,更多的是客户端通过请求的参数来实现在服务端的具体操作,并最终返回数据给客户端.因为我们不 ...
随机推荐
- 【现代程序设计】【homework-04】
Personal Software Process Stages 时间百分比(%) 实际花费的时间 (分钟) 原来估计的时间 (分钟) 计划 0 0 0 · 估计这个任务需要多少时 ...
- sublime text2注册码
----- BEGIN LICENSE ----- Andrew Weber Single User License EA7E-855605 813A03DD 5E4AD9E6 6C0EEB94 BC ...
- [OC Foundation框架 - 20] 统计代码行数
注意: 1.变量名和函数名不要混淆调用 2.不要对文件夹进行文件的操作,没有权限 3.递归调用注意初始化变量 // // main.m // CodeLineCount // // Created ...
- java中几个特殊的类
1 内部类-----是在其他类中的类 1.1 内部类的定义 将类定义为 class xxxx{... ...}置于某个类的内部即可‘ 内部类编译时生成 xxxx$xxxx的class文件 内部类不能够 ...
- Python用特殊符号切割字符串并生成list(简单)
采用re模块,可以指定字符进行切割,例如切割IP地址: import socket import re localIP = socket.gethostbyname(socket.gethostnam ...
- 关于iOS中SQLITE句柄的使用的细节
1.设计思想:给SQLITE进行封装,利用定义的类别实现方法的简洁,以便达到低耦合效果 控制器代码: #import "ViewController.h" #import &quo ...
- java反射快速入门(一)
本文会从以下几个方面讲起 ① 反射的简单解释 ② java反射的API接口 及 demo ③ 反射的优缺点.应用场景 一.什么是反射? java反射:在程序运行中动态获取类的信息,及动态调用对象的方法 ...
- DSC配置
#配置Remote Desktop Services服务为 自启动,并运行 Configuration Myservice{ # A Configuration block can have zero ...
- Thread学习
1.定义 2.作用 3.和进程的比较 4.多线程(multithreading)的优点和缺陷 5.调度(scheduling) 6.线程相关概念 定义 线程就是最小的可编程指令序列,是进程的子集.一个 ...
- Linux开发环境搭建与使用——ubuntu更新设置
ubuntu操作系统公布时,为了减小操作系统的体积,只配备了主要的系统软件.应用软件.我们开发中须要用到的大部分软件都须要在使用中从网上自行更新. 假设ubuntu没有网络,能够说寸步难行. 以下教大 ...