okhttp源码学习分析一
16lz
2021-01-24
okhttp源码学习分析一
- 同步请求
- RealCall 的execute方法
- 异步请求
- enqueue源码
同步请求
public class GetExample { OkHttpClient client = new OkHttpClient(); String run(String url) throws IOException { //包含请求头,url,请求参数 Request request = new Request.Builder() .url(url) .build(); //newcall方法创建了realcall try (Response response = client.newCall(request).execute()) { return response.body().string(); } } public static void main(String[] args) throws IOException { GetExample example = new GetExample(); String response = example.run("https://raw.github.com/square/okhttp/master/README.md"); System.out.println(response); }}
RealCall 的execute方法
@Override public Response execute() throws IOException { synchronized (this) { //同一个RealCall 只能同时执行一个请求 if (executed) throw new IllegalStateException("Already Executed"); executed = true; } captureCallStackTrace(); timeout.enter(); eventListener.callStart(this); try { //将请求添加到dispatcher分发器里 client.dispatcher().executed(this); //通过拦截链获取最后的结果,拦截链设计的很巧妙 Response result = getResponseWithInterceptorChain(); if (result == null) throw new IOException("Canceled"); return result; } catch (IOException e) { e = timeoutExit(e); eventListener.callFailed(this, e); throw e; } finally { //在分发器里将本次请求去掉 client.dispatcher().finished(this); } }
异步请求
client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } });
enqueue源码
@Override public void enqueue(Callback responseCallback) { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } captureCallStackTrace(); eventListener.callStart(this); //分发器里添加该请求 client.dispatcher().enqueue(new AsyncCall(responseCallback)); }
查看dispatcher的enqueue
/** Ready async calls in the order they'll be run. */ //准备执行异步的请求 private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>(); /** Running asynchronous calls. Includes canceled calls that haven't finished yet. */ //正在执行的异步请求 private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>(); /** Running synchronous calls. Includes canceled calls that haven't finished yet. */ private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>(); void enqueue(AsyncCall call) { synchronized (this) { //将该请求放到准备执行的异步请求栈里 readyAsyncCalls.add(call); // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to // the same host. if (!call.get().forWebSocket) { AsyncCall existingCall = findExistingCallWithHost(call.host()); if (existingCall != null) call.reuseCallsPerHostFrom(existingCall); } } promoteAndExecute(); }
private boolean promoteAndExecute() { assert (!Thread.holdsLock(this)); List<AsyncCall> executableCalls = new ArrayList<>(); boolean isRunning; synchronized (this) { for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) { AsyncCall asyncCall = i.next();//根据最大请求数,将准备执行的网络请求添加到正在执行的网络请求栈中 if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity. if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity. i.remove(); asyncCall.callsPerHost().incrementAndGet(); executableCalls.add(asyncCall); runningAsyncCalls.add(asyncCall); } isRunning = runningCallsCount() > 0; } for (int i = 0, size = executableCalls.size(); i < size; i++) { AsyncCall asyncCall = executableCalls.get(i); asyncCall.executeOn(executorService()); } return isRunning; }
dispatcher类将多个网络请求进行分发管理。
更多相关文章
- Android倒计时实现
- android dialog 背景透明的样式
- Android之动态改变控件大小
- radiolog不全的问题
- Android中调试规范Log
- android音乐播放器(4)
- android service 生命周期
- Android(安卓)获取网络时间
- android 获取web 内容简单实现