1、在4.0之上的手机,在主线程中请求,默认地会抛出一个android.os.NetworkOnMainThreadException的异常,所以需要在异步中进行请求。在定义请求队列的时候,需要构建一些业务层的请求接口,这些接口主要用于上层人员去调用的。对于上层调用人员来说,关心的只是请求成功和失败,它不关心是通过哪种方式去请求的,所以,在设计接口的时候要考虑接口设计的简洁性。
框架要支持多线程的请求,但是对于多线程来说,不可能无限制地开更多的线程,所以会引入队列。队列中存储的东西是对象,
2、请求的封装
public class MoocRequest {
private String mUrl;
private HttpMethod mMethod;
private byte[] mData;
private MoocResponse mResponse;
private String mContentType;
public String getUrl() {
return mUrl;
}
public void setUrl(String url) {
mUrl = url;
}
public HttpMethod getMethod() {
return mMethod;
}
public void setMethod(HttpMethod method) {
mMethod = method;
}
public byte[] getData() {
return mData;
}
public void setData(byte[] data) {
mData = data;
}
public MoocResponse getResponse() {
return mResponse;
}
public void setResponse(MoocResponse response) {
mResponse = response;
}
public String getContentType() {
return mContentType;
}
public void setContentType(String contentType) {
mContentType = contentType;
}
}
3、响应的封装
public abstract class MoocResponse<T> {
public abstract void success(MoocRequest request, T data);
public abstract void fail(int errorCode, String errorMsg);
}
4、WorkStation工作栈主要用来处理队列的请求以及多线程的管理
该框架的设计主要是快速响应用户的请求,比如在1s内同时有几十个用户的请求,要同时处理,所以我们要开更多的线程,但是线程并不是开的无限的大,因为无限的大,资源会有很大的消耗。所以,创建的线程池中第二个参数最大线程数指定无限大Integer.MAX_VALUE.
Deque<MoocRequest> mRunning 、Deque<MoocRequest> mCache 队列主要用来控制对象的长度
public class WorkStation {
private static final int MAX_REQUEST_SIZE = 60;
private static final ThreadPoolExecutor sThreadPool = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new ThreadFactory() {
private AtomicInteger index = new AtomicInteger();
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("http thread name is " + index.getAndIncrement());
return thread;
}
});
private Deque<MoocRequest> mRunning = new ArrayDeque<>();
private Deque<MoocRequest> mCache = new ArrayDeque<>();
private HttpRequestProvider mRequestProvider;
public WorkStation() {
mRequestProvider = new HttpRequestProvider();
}
public void add(MoocRequest request) {
if (mRunning.size() > MAX_REQUEST_SIZE) {
mCache.add(request);
} else {
doHttpRequest(request);
mRunning.add(request);
}
}
public void doHttpRequest(MoocRequest request) {
HttpRequest httpRequest = null;
try {
httpRequest = mRequestProvider.getHttpRequest(URI.create(request.getUrl()), request.getMethod());
} catch (IOException e) {
e.printStackTrace();
}
sThreadPool.execute(new HttpRunnable(httpRequest, request, this));
}
public void finish(MoocRequest request) {
mRunning.remove(request);
if (mRunning.size() > MAX_REQUEST_SIZE) {
return;
}
if (mCache.size() == 0) {
return;
}
Iterator<MoocRequest> iterator = mCache.iterator();
while (iterator.hasNext()) {
MoocRequest next = iterator.next();
mRunning.add(next);
iterator.remove();
doHttpRequest(next);
}
}
}
5、
public class HttpRunnable implements Runnable {
private HttpRequest mHttpRequest;
private MoocRequest mRequest;
private WorkStation mWorkStation;
public HttpRunnable(HttpRequest httpRequest, MoocRequest request, WorkStation workStation) {
this.mHttpRequest = httpRequest;
this.mRequest = request;
this.mWorkStation = workStation;
}
@Override
public void run() {
try {
mHttpRequest.getBody().write(mRequest.getData());
HttpResponse response = mHttpRequest.execute();
String contentType = response.getHeaders().getContentType();
mRequest.setContentType(contentType);
if (response.getStatus().isSuccess()) {
if (mRequest.getResponse() != null) {
mRequest.getResponse().success(mRequest, new String(getData(response)));
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
mWorkStation.finish(mRequest);
}
}
public byte[] getData(HttpResponse response) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream((int) response.getContentLength());
int len;
byte[] data = new byte[512];
try {
while ((len = response.getBody().read(data)) != -1) {
outputStream.write(data, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
return outputStream.toByteArray();
}
}
6、
public class MoocApiProvider {
private static final String ENCODING = "utf-8";
private static WorkStation sWorkStation = new WorkStation();
private static final List<Convert> sConverts = new ArrayList<>();
static {
sConverts.add(new JsonConvert());
}
public static byte[] encodeParam(Map<String, String> value) {
if (value == null || value.size() == 0) {
return null;
}
StringBuffer buffer = new StringBuffer();
int count = 0;
try {
for (Map.Entry<String, String> entry : value.entrySet()) {
buffer.append(URLEncoder.encode(entry.getKey(), ENCODING)).append("=").
append(URLEncoder.encode(entry.getValue(), ENCODING));
if (count != value.size() - 1) {
buffer.append("&");
}
count++;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return buffer.toString().getBytes();
}
public static void helloWorld(String ul, Map<String, String> value, MoocResponse response) {
MoocRequest request = new MoocRequest();
WrapperResponse wrapperResponse = new WrapperResponse(response, sConverts);
request.setUrl(ul);
request.setMethod(HttpMethod.POST);
request.setData(encodeParam(value));
request.setResponse(wrapperResponse);
sWorkStation.add(request);
}
}
7、调用方式