2011年的某一天,你的公司初进移动开发领域,上司要求你实现一套http网络请求框架,要求易扩展。
2011年!!!volley、imageloader、fresco、glide…..都是啥?????
为支持多种请求的扩张,这里采用抽象类。
ICallBack
public interface ICallBack {
void onFailure(Exception result);
void onSuccess(Object result);
Object handle(HttpResponse response, IProgressListener iProgressListener);
void onProgressUpdate(int curPos, int contentLength);
/** * 在子线程中对返回值做预处理,比如保存到数据库等等操作(预处理返回的对象) * 如果不需要什么处理的话,什么都不需要做 * @param object * @return */
Object onPreHandle(Object object);
Object onPresRequest();
}
AbstractCallback
public abstract class AbstractCallback implements ICallBack{
public String path;
private static final int IO_BUFFER_SIZE = 4 * 1024;
// 做解析
@Override
public Object handle(HttpResponse response, IProgressListener iProgressListener) {
// file,json,xml,image,string
try {
HttpEntity entity = response.getEntity();
switch (response.getStatusLine().getStatusCode()) {
// 返回时200的时候,我就去解析数据
case HttpStatus.SC_OK:
// 文件,把服务器的返回直接写到文件里面
if (TextUtil.isValidate(path)) {
FileOutputStream fos = new FileOutputStream(path);
InputStream in = null;
if (entity.getContentEncoding() != null) {
String encoding = entity.getContentEncoding().getValue();
if (encoding != null && "gzip".equalsIgnoreCase(encoding)) {
in = new GZIPInputStream(entity.getContent());
} else if (encoding != null && "deflate".equalsIgnoreCase(encoding)) {
in = new InflaterInputStream(entity.getContent());
}
} else {
in = entity.getContent();
}
byte[] b = new byte[IO_BUFFER_SIZE];
int read;
long curPos = 0;
// long length = entity.getContentLength();
while ((read = in.read(b)) != -1) {
// update progress
curPos += read;
iProgressListener.onProgressUpdate((int) (curPos / 1024), (int) (entity.getContentLength()));
fos.write(b, 0, read);
}
fos.flush();
fos.close();
in.close();
return bindData(path);
} else {
return bindData(EntityUtils.toString(entity));
}
default:
break;
}
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected Object bindData(String content) {
return content;
}
public AbstractCallback setPath(String path) {
this.path = path;
return this;
}
}
StringCallBack
public abstract class StringCallBack extends AbstractCallback{
@Override
protected Object bindData(String content) {
if (TextUtil.isValidate(path)) {
return FileUtil.readFromFile(path);
}
return content;
}
}
public class Request {
public enum RequestMethod {
GET, POST, DELETE, PUT
}
public RequestMethod method;
public String url;
public String postContent;
public Map<String, String> headers;
public HttpEntity entity;
public static final String ENCODING = "UTF-8";
public ICallBack mCallback;
public Request(String url, RequestMethod method) {
this.url = url;
this.method = method;
}
// 表单形式
public void setEntity(ArrayList<NameValuePair> forms) {
try {
entity = new UrlEncodedFormEntity(forms, ENCODING);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
// string
public void setEntity(String postContent) {
try {
entity = new StringEntity(postContent, ENCODING);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
// array
public void setEntity(byte[] bytes) {
entity = new ByteArrayEntity(bytes);
}
public void setCallback(ICallBack callback) {
mCallback = callback;
}
public void execute() {
RequestTask task = new RequestTask(this);
task.execute();
}
}
public class RequestTask extends AsyncTask<Object, Integer, Object> {
private Request mRequest;
public RequestTask(Request request) {
mRequest = request;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Object doInBackground(Object... params) {
try {
Object object1 = mRequest.mCallback.onPresRequest();
if (object1 != null) {
return object1;
}
HttpResponse response = HttpClientUtil.execute(mRequest);
Object object = mRequest.mCallback.handle(response, new IProgressListener() {
@Override
public void onProgressUpdate(int curPos, int contentLength) {
publishProgress(curPos, contentLength);
}
});
return mRequest.mCallback.onPreHandle(object);
} catch (IOException e) {
e.printStackTrace();
return e;
}
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
mRequest.mCallback.onProgressUpdate(values[0], values[1]);
}
@Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
if (result instanceof Exception) {
mRequest.mCallback.onFailure((Exception) result);
} else {
mRequest.mCallback.onSuccess(result);
}
}
}
public class HttpClientUtil {
public static HttpResponse execute(Request request) throws IOException {
switch (request.method) {
case GET:
return get(request);
case POST:
return post(request);
default:
throw new IllegalStateException("the method" + request.method.name() + "doesn't support");
}
}
private static HttpResponse post(Request request) throws IOException {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(request.url);
addHeader(post, request.headers);
if (request.entity == null) {
throw new IllegalStateException("you forget to set post content to the HttpPost");
} else {
post.setEntity(request.entity);
}
HttpResponse response = client.execute(post);
return response;
}
private static HttpResponse get(Request request) throws IOException {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(request.url);
addHeader(get, request.headers);
HttpResponse response = client.execute(get);
return response;
}
public static void addHeader(HttpUriRequest request, Map<String, String> headers) {
if (headers != null && headers.size() > 0) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
request.addHeader(entry.getKey(), entry.getValue());
}
}
}
}
略过
这里实现了常见的回调:进度、成功、失败,并且支持对多种格式的请求扩展。封装了httpurlconnection、httpclient两种方式。
很多问题:比如用的是异步任务等等,android3.0后,异步任务变为串行的了,并且异步任务的可扩展性非常的低,下面我们会讲解另一种实现方式:ThreadPool+Runnable+Handler,SimpleNet就是这种实现方式,后面也会专门写一篇博客来分析这个。
仅供学习使用
Q:框架和库(工具包)的区别?
A:框架与库和工具包看起来很类似-都是提供了一系列api。他们的不同在于:库和工具包是为程序员带来自由的,框架则是为了给程序员带来约束的。具体来说:库和工具包是为了给程序员提供武器装备的,框架则利用控制反转机制实现对各模块的统一调度。
Q:现在网络框架那么多,volley、universal image loader、fresco、Picasso、glide、okhttp,怎么办?
A:感觉重点是原理,都是为了解决同样的问题,比较来说,可能就是某个框架在解决某个问题时可能更出色一点而已.
以上网络框架仅供学习使用,不要用在工业级项目中!!!
https://github.com/zhujainxipan/FYForAndroidTest