用了那么久的NoHttp这么强大的网络库,但是对里面的源码都是一知半解,只会去怎么去使用,但不了解这个流程是怎样的,俗话说的好,“授人以鱼 不如授如以渔”~单单就会使用,怎么能称的上是合格的程序猿,向着大神看起,学习他们的思想设计~
本人还是名小白,本文还有欠缺考虑的地方请见谅
如果不知道NoHttp的话,
请看严振杰的博客 http://blog.csdn.net/yanzhenjie1003
请看NoHttp github 链接:https://github.com/yanzhenjie/NoHttp
———————我是一条分割线———————–
先看下作者说的源码核心流程是怎样的
这是异步请求 也是大部分应用都是调用这个 版本号1.0.0
那我们就遵循上面流程 一步步看 作者是如何做到的
NoHttp.init(application) 这个初始化 就不用说了 传入上下文 和设置 默认的 CookieManger
当面我们每次构建 request对象 需要 传入到 RequestQueue 请求的线程池中,建议这里写成单例~
public static RequestQueue newRequestQueue(Cache cache, int threadPoolSize) {
return newRequestQueue(HttpRestConnection.getInstance(cache), threadPoolSize);
}
public static RequestQueue newRequestQueue(ImplRestConnection implRestConnection, int threadPoolSize) {
return newRequestQueue(HttpRestParser.getInstance(implRestConnection), threadPoolSize);
}
public static RequestQueue newRequestQueue(ImplRestParser implRestParser, int threadPoolSize) {
RequestQueue requestQueue = new RequestQueue(implRestParser, threadPoolSize);
requestQueue.start();
return requestQueue;
}
上面一步步的单例的形式 都是为了 后面做铺垫的,下文 有解析~
这里构造的方法最终都是到达 newRequestQueue(ImplRestParser implRestParser, int threadPoolSize)
开启 线程池 requestQueue.start();
public void start() {
stop();
for (int i = 0; i < mDispatchers.length; i++) {
RequestDispatcher networkDispatcher = new RequestDispatcher(mUnFinishQueue, mRequestQueue, mImplRestParser);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}
这里就是创建一个 RequestDispatcher 子线程 去轮训这个线程池,mImplRestParser这个 相应解析者同时子线程里,作者说这里面是真正的请求网络的线程咯。
那我们就仔细深入看看着个类里 是怎么做到的
public class RequestDispatcher extends Thread
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
while (!mQuit) {
final Request> request;
try {
request = mRequestQueue.take();
} catch (InterruptedException e) {
if (!mQuit)
return;
continue;
}
if (request.isCanceled()) {
Logger.d(request.url() + " is canceled.");
continue;
}
final int what = request.what();
final OnResponseListener> responseListener = request.responseListener();
request.start();
// start
final ThreadPoster startThread = new ThreadPoster(what, responseListener);
startThread.onStart();
PosterHandler.getInstance().post(startThread);
// request
Response> response = mImplRestParser.parserRequest(request);
// remove it from queue
mUnFinishQueue.remove(request);
// finish
final ThreadPoster finishThread = new ThreadPoster(what, responseListener);
finishThread.onFinished();
PosterHandler.getInstance().post(finishThread);
request.finish();
// response
if (request.isCanceled())
Logger.d(request.url() + " finish, but it's canceled.");
else {
final ThreadPoster responseThread = new ThreadPoster(what, responseListener);
responseThread.onResponse(response);
PosterHandler.getInstance().post(responseThread);
}
}
}
RequestDispatcher 其实就是一个线程,不断的从RequestQueue请求队列中take(),如果为空 也不阻塞主线程 因为这是在子线程里操作的~并且 未请求的消息 如果被取消 也会同时取消掉,不会发起请求的~
这个responseListener接口 回调里记录发起请求 开始 结束等状态,最后在未完成的线程池中 移除请求
mUnFinishQueue.remove(request);最终handler发送回主线程上 返回服务器请求结果。
// 用IRestParser发送请求,并解析结果,这就是上文中说过的。
Response> response = mIRestParser.parserRequest(request);
IRestParser这个响应解析类是 很关键 还没到达网络请求 连接的部分,这个只是个接口,它的实现类 按Ctrl+T可以看到它的实现类,RestParser这个类是它的实现类,通过之前的构造获取到IRestParser的实例
public static RequestQueue newRequestQueue(IRestProtocol iRestProtocol, int threadPoolSize) {
return newRequestQueue(RestParser.getInstance(iRestProtocol), threadPoolSize);
}
这里可以理解为Nohttp的同步请求开始
// 调用Http协议处理器IRestProtocol分析Request并完成网络请求拿到Response结果。
mIRestProtocol.requestNetwork(request);
同样类似IRestParser,IRestProtocol也只是一个接口,它的实现类是RestProtocol这个类,这里会根据Nohttp的缓存模式 来进行请求,具体还是看下demo.
这个类中 RestProtocol的
getHttpResponse(request);
这是作者说的 那我们就在看下吧~核心中的核心咯
/**
* 真正的请求网络。
*/
private ProtocolResult getHttpResponse(IProtocolRequest request) {
byte[] responseBody = null;
Connection connection = iRestConnection.getConnection(request); // 从IRestConnection拿到网络连接和响应内容。
Headers responseHeaders = connection.responseHeaders();
Exception exception = connection.exception();
if (exception == null) {
// 判断是否有响应内容,比如304响应码就没有body。
if (hasResponseBody(request.getRequestMethod(), responseHeaders.getResponseCode()))
try {
// 把服务器响应body转为ByteArray。
responseBody = IOUtils.toByteArray(connection.serverStream());
} catch (IOException e) {// IOException.
exception = e;
}
}
IOUtils.closeQuietly(connection); // 关闭服务器流。
// 返回响应内容。
return new ProtocolResult(responseHeaders, responseBody, exception != null, exception);
}
Connection 这个接口类就实现了
public interface Connection extends Closeable {
/**
* 拿到URL对象。
*/
URL getURL();
/**
* 拿到相应头。
*/
Headers responseHeaders();
/**
* 拿到服务器的输出流。
*/
InputStream serverStream();
/**
* 拿到请求过程中的异常。
*/
Exception exception();
}
只要实现上述的方法 就可以替换成底层的类,Okhtttp也可以和Nohttp 具体看详细链接吧~
传送门在此 http://blog.csdn.net/yanzhenjie1003/article/details/52413226
在其中 HttpRestParser 和 HttpRestConnection 这里 应该是请求的过程核心之一,根据request 的缓存模式来进行网络请求,可以看得出来 底层是HttpURLConnection 和 OKHttp一样
protected Connection getConnection(BasicServerRequest request) {
Logger.d("--------------Request start--------------");
Headers responseHeaders = new HttpHeaders();
InputStream inputStream = null;
Exception exception = null;
HttpURLConnection urlConnection = null;
String url = request.url();
try {
if (!NetUtil.isNetworkAvailable())
throw new NetworkError("The network is not available, please check the network. The requested url is: " + url);
// MalformedURLException, IOException, ProtocolException, UnknownHostException, SocketTimeoutException
urlConnection = createHttpURLConnection(request);
Logger.d("-------Response start-------");
int responseCode = urlConnection.getResponseCode();
responseHeaders = parseResponseHeaders(new URI(request.url()), responseCode, urlConnection.getResponseMessage(), urlConnection.getHeaderFields());
// handle body
if (responseCode == 301 || responseCode == 302 || responseCode == 303 || responseCode == 307) {
Connection redirectConnectiont = handleRedirect(request, responseHeaders);
responseHeaders = redirectConnectiont.responseHeaders();
inputStream = redirectConnectiont.serverStream();
exception = redirectConnectiont.exception();
} else if (hasResponseBody(request.getRequestMethod(), responseCode)) {
inputStream = getServerStream(responseCode, responseHeaders.getContentEncoding(), urlConnection);
}
Logger.d("-------Response end-------");
} catch (MalformedURLException e) {
exception = new URLError("The url is malformed: " + url + ".");
} catch (UnknownHostException e) {
exception = new UnKnownHostError("Hostname can not be resolved: " + url + ".");
} catch (SocketTimeoutException e) {
exception = new TimeoutError("Request time out: " + url + ".");
} catch (Exception e) {
exception = e;
} finally {
if (exception != null)
Logger.e(exception);
}
Logger.d("--------------Request finish--------------");
return new Connection(urlConnection, responseHeaders, inputStream, exception);
}
看了一圈下来 最主要看到那个几个核心处理的类,要好好理解 为啥 这样分层次,如何解耦~ 我要好好膜拜作者去了~~~吃瓜群众路过~