Android学习之——自己搭建Http框架(1)

一、前言

? ? ? ? 近期学习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.傅

? ? ? ??

原文地址:https://www.cnblogs.com/mqxnongmin/p/10515765.html

时间: 2024-10-21 02:14:18

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

Android学习之——自己搭建Http框架

一.前言 最近学习http框架. 目前写的这个框架暂时只适用于学习之用,实际用于项目之中还需要不断的优化. 要从服务器或者网络获取数据,显示到UI上面,网络请求的操作不能放在UI线程中进行,android为我们封装了AsyncTask类来进行异步的请求操作,所以这个Http框架基于AsyncTask. 二.框架主要类 定义Request类,定义url,服务器返回数据,post的请求params,下载进度等参数. 定义HttpUtil类来封装http请求代码.在里面定义execute()方法,该方

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

· 本文主要讲解的是Json指定转化成对象返回,下载进度更新,随时取消Request请求 一.Json指定转化成对象返回 上篇文章主要讲基础的框架搭建起来了,这次需要做一些些的扩展,这里Json转化用到了google的Gson. 上篇文章,我们直接返回了String的字符串,那么如果是请求返回回来的是Json格式的,我们能否在数据返回的时候将数据转化成需要的对象呢.答案当然是可以的. 我们可以在UI线程中创建Callback的时候将预处理的对象放入进去,还是直接代码描述比较清楚:        

Android学习之环境搭建

Android学习之环境搭建 园里有很多关于Android开发的环境搭建的资料,本人是安卓开发初学者,这里记录一下个人搭建Android环境的总结. 1.准备Eclipse IDE for Java Developers 网上可以下载的版本还是比较多的,本人选择了eclipse-java-luna-SR2-win32. 网址:http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/lunasr2 Note:官网点

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

PS:看完了LGD的六场比赛...让人心酸... 学习内容: 1.Http请求的过程... 2.Volley的简单介绍...   1.Http请求...   这里只是简单的说一下Http请求的过程...非常的简单...首先是发送Request..然后服务器在获取到Request请求后会对其进行相应的处理,然后以Response的形式进行返回,然后分配Response,即谁发送的请求,那么响应就分配给谁... 2.Volley简单介绍...   这里只是先简单的说一下Volley,Volley框架

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

学习内容: 1.PoolingByteArrayOutputStream 2.ByteArrayPool 3.HttpStack 4.HurlStack 5.HttpHeaderParser   前面整体的解释了网络请求——响应的整个过程,只是其中还是涉及到了一些其他的类,因此在这里都说一说,最后几篇会是Volley正式做一些请求,这篇仍然是进行源码解析... 1.PoolingByteArrayOutputStream.java   PoolingByteArrayOutputStream继承

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

学习内容: 1.NetWorkDispatcher网络请求线程调度... 2.NetWork网络请求抽象类... 3.BasicNetWork网络请求抽象类的具体实现... 4.NetWorkResponse接收网络请求返回的响应... 5.ResponseDelivery请求分配抽象类... 6.ExecutorDelivery请求分配的具体实现类...   上一章说完了缓存请求线程调度,那么现在就说一下网络请求线程调度是如何来完成的,网络请求线程调度也是有一个核心过程的,从网络上获取数据信息

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

PS:Volley已经学完,可以安心的写一下博客总结一下了... 学习内容: 1.Request的完整封装... 2.RetryPolicy,DefaultRetryPolicy(请求重试策略源码解析) 3.RequestQueue(请求队列源码解析)   RequestQueue(源码解析)...   RequestQueue顾名思义,请求队列,Volley中采用请求队列来管理所有正在提交的Request,将所有封装好的Request保存在其内部,方便管理...而一个Request需要被完整的

【JAVA学习】05.搭建SSM框架

[提要]SSM(Spring+SpringMVC+MyBatis) [步骤] 1. [注意] 1.项目文件目录默认是扁平的,甚是难看,可将其换成树状结构: 文件目录右上方有下向下图标,点开后选择Package Presentation,展开后选择 Hierarchical: 原文地址:https://www.cnblogs.com/pbping/p/9059956.html

【转】Android开发学习总结(一)——搭建最新版本的Android开发环境

最近由于工作中要负责开发一款Android的App,之前都是做JavaWeb的开发,Android开发虽然有所了解,但是一直没有搭建开发环境去学习,Android的更新速度比较快了,Android1.0是2008年发布的,截止到目前为止Android已经更新Android5.0.1,学习Android开发的第一步就是搭建Android的开发环境,博客园里面有不少人也写了关于如何搭建Android开发环境的文章,我也看了一下,但是感觉都比较旧了,对照着做不一定能够搭建成功,但是有些搭建步骤是还是可