一、前言

        近期学习http框架。

        眼下写的这个框架临时仅仅适用于学习之用,实际用于项目之中还须要不断的优化。

        要从server或者网络获取数据。显示到UI上面,网络请求的操作不能放在UI线程中进行,android为我们封装了AsyncTask类来进行异步的请求操作。所以这个Http框架基于AsyncTask。

二、框架主要类

        定义Request类,定义url。server返回数据,post的请求params,下载进度等參数。

        定义HttpUtil类来封装http请求代码。

在里面定义execute()方法,该方法推断是get还是post。然后再去call get(),post() 方法。post() 请求须要的參数在Request中设置.

        在AsyncTask中。doingBackground()方法中 execute http。将返回的数据写到内存中变成String返回,假设数据较大,能够先存到文件里。把path返回。在不同的callback中处理。

三、框架搭建

        1. 首先,我们建立 HttpClientUtil.java 类,用于处理HTTP的get和post,里面定义execute()方法。该方法推断是get还是post,然后再去call get(),post() 方法。post()
请求须要的參数在Request中设置.:

/**
* @author Mr.傅
*/
public class HttpClientUtil {
/**
* 运行HTTP方法,Request 设置请求类型
* @param request
* @return
* @throws Exception
*/
public static HttpResponse excute(Request request) throws Exception{
switch (request.requestMethod) {
case GET:
return get(request);
case POST:
return post(request);
default:
//这里未定义 DELETE 和 PUT 操作
throw new IllegalStateException("you doesn't define this requestmethod");
}
} private static HttpResponse get(Request request) throws Exception {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(request.url);
addHeader(get, request.headers);
//返回的结果放到上一层进行处理
HttpResponse response = client.execute(get);
return response;
} private static HttpResponse post(Request request) throws Exception {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(request.url);
addHeader(post, request.headers);
//post的请求參数在 Request 中定义,假设为空,则未定义
if (request.entity == null) {
throw new IllegalStateException("you forget to set post content to the httpost");
}else {
post.setEntity(request.entity);
}
HttpResponse response = client.execute(post);
return response;
} /**
* 请求头
* @param request
* @param headers
*/
public static void addHeader(HttpUriRequest request, Map<String, String> headers){
if (headers != null && headers.size() > 0 ) {
for(Entry<String, String> entry : headers.entrySet()){
request.addHeader(entry.getKey(), entry.getValue());
}
}
}
}

        2. 上述代码中的 Request.java 类,定义url。server返回数据。post的请求params,下载进度等參数定义例如以下:

/**
* @author Mr.傅
*/
public class Request {
public enum RequestMethod{
GET,POST,DELETE,PUT
}
RequestMethod requestMethod;
public String url;
/**
* Http请求參数的类型。包含表单。string, byte等
*/
public HttpEntity entity;
public Map<String, String> headers;
public static final String ENCODING = "UTF-8";
/**
* 设置回调接口,该接口中的onSuccess和onFilure方法须要在体如今UI线程其中
*/
public ICallback callback;
private RequestTask task; public Request(String url, RequestMethod method) {
this.url = url;
this.requestMethod = method;
}
public void setEntity(ArrayList<NameValuePair> forms){
try {
entity = new UrlEncodedFormEntity(forms, ENCODING);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public void setEntity(String postContent){
try {
entity = new StringEntity(postContent, ENCODING);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public void setEntity(byte[] bytes){
entity = new ByteArrayEntity(bytes);
} /**
* 设置回调方法,在ui线程中定义须要请求 返回的 方法
* @param callback
*/
public void setCallback(ICallback callback) {
this.callback = callback;
} /**
* UI线程中,运行该方法,开启一个AsyncTask,注意AsyncTask每次使用必须又一次new
*/
public void execute() {
task = new RequestTask(this);
task.execute();
}
}

 
      3. ICallback接口。该接口的onFilure和onSuccess方法在UI线程其中实现,假设在RequestTask中doInBackground中HttpResponse返回成功则在onPostExecute中调用onSuccess。否则调用onFilure,并传递已经解析了的返回參数:

public interface ICallback {
void onFilure(Exception result);
void onSuccess(Object result);
/**
* 将从server得到的HttpResponse进行解析,解析完毕以后。返回给UI线程
*/
Object handle(HttpResponse response);
}

        4. RequestTask 继承自 AsyncTask ,在doInBackground 进行HTTP请求。同一时候对HTTP请求返回的数据结果进行解析,通过调用callback中的handle方法。解析HTTP请求返回的參数,返回后的结果(假设抛出异常,将异常也返回)。在onPostExecute中进行处理,调用不同的方法。返回到UI线程,代码例如以下:

/**
* @author Mr.傅
* @version create time:2014年5月17日 下午2:19:39
*/
public class RequestTask extends AsyncTask<Object, Integer, Object> {
private Request request; public RequestTask(Request request) {
super();
this.request = request;
}
@Override
protected Object doInBackground(Object... params) {
try {
HttpResponse response = HttpClientUtil.excute(request);
//response 解析代码放到相应的类中,相应handle中的bindData方法
return request.callback.handle(response);
} catch (Exception e) {
return e;
}
} @Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
if (result instanceof Exception) {//失败
request.callback.onFilure((Exception)result);
}else {//成功
request.callback.onSuccess(result);
}
}
}

        5. AbstractCallback.java 该类 中实现接口 ICallback 的 handle 方法,该方法主要作用是。对HTTP返回的HttpResponse 进行解析,假设返回状态码是200。则进行下一步处理;假设UI调用了setPath()方法,设置了保存的路径的话。就将HTTP返回的数据先写入到文件里。然后文件里读取出来,放入到相应的解析实现类中,如:StringCallback,JsonCallback等。
返回到doInBackground 中(doInBackground 中的return request.callback.handle(response)步骤)。假设没有设置路径,则直接调用bindData(EntityUtils.toString(entity)),
放入到详细的Callback中进行处理,然后返回到doInBackground中进行下一步处理。

/**
* @author Mr.傅
*/
public abstract class AbstractCallback implements ICallback{
/**
* 文件存放的路径
*/
public String path;
private static final int IO_BUFFER_SIZE = 4*1024; @Override
public Object handle(HttpResponse response){
// file, json, xml, image, string
int statusCode = -1;
InputStream in = null;
try {
HttpEntity entity = response.getEntity();
statusCode = response.getStatusLine().getStatusCode();
switch (statusCode) {
case HttpStatus.SC_OK:
if (TextUtil.isValidate(path)) {
//将server返回的数据写入到文件其中
FileOutputStream fos = new FileOutputStream(path);
if (entity.getContentEncoding() != null) {
String encoding = entity.getContentEncoding().getValue();
if (encoding != null && "gzip".equalsIgnoreCase(encoding)) {
in = new GZIPInputStream(entity.getContent());
} if (encoding != null && "deflate".equalsIgnoreCase(encoding)) {
in = new InflaterInputStream(entity.getContent());
}
} else {
in = entity.getContent();
}
byte[] b = new byte[IO_BUFFER_SIZE];
int read;
while ((read = in.read(b)) != -1) {
// TODO update progress
fos.write(b, 0, read);
}
fos.flush();
fos.close();
in.close();
//写入文件之后。再从文件其中将数据读取出来。直接返回对象
return bindData(path);
} else {
// 须要返回的是对象,而不是数据流,所以须要去解析server返回的数据
// 相应StringCallback 中的return content;
//2. 调用binData
return bindData(EntityUtils.toString(entity));
}
default:
break;
}
return null;
} catch (ParseException e) {
//这些异常处理都没有进行操作。后面的文章会再做处理
} catch (IOException e) {
}
return null;
} /**
* 数据放入到不同的Callback中处理
*/
protected Object bindData(String content){
//StringCallback等方法中实现了该方法
return null;
} /**
* 假设要存入到文件,则设置文件路径
*/
public AbstractCallback setPath(String path){
this.path = path;
return this;
}
}

        6. StringCallback.java 眼下的代码,仅仅实现了该callback,JsonCallback,PathCallback,会在后面的文章其中详细实现:

public abstract class StringCallback extends AbstractCallback {
@Override
protected Object bindData(String content) {
//假设路径存在,则又一次讲数据从文件里读取出来
if (TextUtil.isValidate(path)) {
return IOUtiliteies.readFromFile(path);
}
return content;
}
}

 
      7. 其中用到的TextUtil.java 类 

public class TextUtil {
public static boolean isValidate(String content){
return content != null && !"".equals(content.trim());
}
public static boolean isValidate(ArrayList<NameValuePair> content){
return content != null && content.size() > 0;
}
}

        8. UI线程中详细调用方法例如以下:

private void requestString() {
//设置保存路径
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "mrfu_http.txt";
Request request = new Request("http://www.baidu.com", RequestMethod.GET);
request.setCallback(new StringCallback() {
@Override
public void onSuccess(Object result) {
mTestResultLabel.setText((String)result);
} @Override
public void onFilure(Exception result) {
result.printStackTrace();
}
}.setPath(path));
request.execute();
}

        其中mTestResultLabel 是TextView

       能够看到实现效果。这里我们在SD卡的根文件夹下将返回结果存入到了 "mrfu_http.txt" 文件里,同一时候显示到了 UI 上面:如图所看到的:

        这里的这仅仅是一个最初步的框架,能够看到非常多的操作都没有处理,如 Json解析,下载进度更新。随时取消请求,对返回的对象进行预处理操作。以及异常处理都没有详细的去实现,并且里面的一些代码结构也不够完好,如直接对Object进行操作。

        后面的文章中会将该框架逐步晚上,包含上面提到的。

        特别感谢stay老师在这其中的帮助。

让我在框架学习这块实打实的迈出了第一步!

欢迎转载。转载注明出处,谢谢
Mr.傅

        

Android学习之——自己搭建Http框架(1)的更多相关文章

  1. Android学习之——自己搭建Http框架(2)——框架扩展

    · 本文主要解说的是Json指定转化成对象返回.下载进度更新,随时取消Request请求 一.Json指定转化成对象返回 上篇文章主要讲基础的框架搭建起来了,这次须要做一些些的扩展,这里Json转化用 ...

  2. Android学习——windows下搭建Cygwin环境

    在上一篇博文<Android学习——windows下搭建NDK_r9环境>中,我们详细的讲解了在windows下进行Android NDK开发环境的配置,我们也讲到了在NDk r7以后,我 ...

  3. Android学习——windows下搭建NDK_r9环境

    1. NDK(Native Development Kit) 1.1 NDK简介 Android NDK是一套允许开发人员使用本地代码(如C/C++)进行Android APP功能开发的工具,通过这个 ...

  4. Android 学习笔记之Volley开源框架解析(一)

    PS:看完了LGD的六场比赛...让人心酸... 学习内容: 1.Http请求的过程... 2.Volley的简单介绍...   1.Http请求...   这里只是简单的说一下Http请求的过程.. ...

  5. Android 学习笔记之Volley开源框架解析(五)

    学习内容: 1.PoolingByteArrayOutputStream 2.ByteArrayPool 3.HttpStack 4.HurlStack 5.HttpHeaderParser   前面 ...

  6. Android 学习笔记之Volley开源框架解析(四)

    学习内容: 1.NetWorkDispatcher网络请求线程调度... 2.NetWork网络请求抽象类... 3.BasicNetWork网络请求抽象类的具体实现... 4.NetWorkResp ...

  7. Android 学习笔记之Volley开源框架解析(二)

    PS:Volley已经学完,可以安心的写一下博客总结一下了... 学习内容: 1.Request的完整封装... 2.RetryPolicy,DefaultRetryPolicy(请求重试策略源码解析 ...

  8. Android使用动态代理搭建网络模块框架

    1.Java中的动态代理相信大多数朋友都接触过,在此就不再赘述,如果有不明白的朋友,可以到网上搜一下(一搜一大堆,呵呵..) 2.本节主要阐述一下如何使用动态代理框架实现Android应用的瘦身开发. ...

  9. Android 学习笔记之Volley开源框架解析(三)

      学习内容: 1.CacheDispatcher缓存请求调度... 2.Cache缓存数据的保存... 3.DiskBasedCache基于磁盘的缓存类实现方式...   前面说到使用Volley发 ...

随机推荐

  1. VC++窗口创建过程,图形绘制,时钟程序

    创建窗口步骤: (1)注册窗口类(RegisterClassEx) (2)创建窗口(CreateWindowEx) (3)在桌面显示窗口(ShowWindow) (4)更新窗口客户区(UpdateWi ...

  2. 常用的7个SQl优化技巧

    作为程序员经常和数据库打交道的时候还是非常频繁的,掌握住一些Sql的优化技巧还是非常有必要的.下面列出一些常用的SQl优化技巧,感兴趣的朋友可以了解一下. 1.注意通配符中Like的使用 以下写法会造 ...

  3. JAVA通过XPath解析XML性能比较

    转自[http://www.cnblogs.com/mouse-coder/p/3451243.html] 最近在做一个小项目,使用到XML文件解析技术,通过对该技术的了解和使用,总结了以下内容. 1 ...

  4. RocketMQ 主从同步机制

    主从同步(HA 高可用) 主从同步原理: 为了保证系统的高可用,消息到达主服务器后,需要将消息同步到从服务器.如果主服务器宕机,消费者可用从从服务器拉取消息. 大体步骤: 1.主服务器启动,监听从服务 ...

  5. Activity正确获取View宽高

    在View的measure完成后,一般可以通过getMeasureWidth/getMeasureWidth方法可以正确的获取View的宽高,而在特殊情况下,可能需要多次measure才能确定最终的测 ...

  6. HDU2389(KB10-F 二分图最大匹配Hopcroft_Karp)

    Rain on your Parade Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 655350/165535 K (Java/Ot ...

  7. 【 js 基础 】【读书笔记】作用域和闭包

    一.编译过程 常见编译性语言,在程序代码执行之前会经历三个步骤,称为编译. 步骤一:分词或者词法分析 将由字符组成的字符串分解成有意义的代码块,这些代码块被称为词法单元. 例子:  var a = 2 ...

  8. 盲刷bios

    本帖最后由 evayh 于 2011-12-17 13:09 编辑 先看看是否是insyde的bios,如果是的话,可以救回来 insyde BIOS在损坏时,会自动进入CRISIS MODE试图刷回 ...

  9. WebSerivce与WebAPI的区别

    一.什么是Web Service Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的.专门的第三方软件或硬件, 就可相互交换数据或集成.依据Web Service规范实施的应 ...

  10. 关于Web中列表页面的加载问题

    2017年5月23日,天气晴朗.尽管昨晚睡的不踏实,好在今天心情还不是很糟糕,近来事情颇多,尤其是对于TA的改变,至少目前还是没有习惯,但时间将会解决一切,这点深有体会.此时此刻,又想起了苏东坡的那首 ...