OkHttp網絡請求框架源碼解析一
基本使用,在app的build.gradle添加依賴
compile 'com.squareup.okhttp3:okhttp:3.8.1'
在配置文件添加網絡訪問權限
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
具體使用流程:
//創建client
OkHttpClient client=new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
//創建request
final Request request=new Request.Builder().url("http://www.baidu.com").get().build();
//調用
Call call=client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("fail",e.toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("baidu:",response.body().string());
}
});
源碼分析:
//第一步:
OkHttpClient client=new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
//其中Builder()方法,初始化一些默認參數,包括Dispatcher的創建,連接池的創建等。
public Builder() {
//核心Dispatcher,call.enqueue()方法最終由dispatcher的enqueue()方法來完成請求。
dispatcher = new Dispatcher();
......
//連接池
connectionPool = new ConnectionPool();
......
}
//其中build()方法,最終獲取OkHttpClient實例。典型的構建者模式。
public OkHttpClient build() {
return new OkHttpClient(this);
}
call.enqueue()方法
//最終調用RealCall裏面的enqueue
@Override public void enqueue(Callback responseCallback) {
//鎖住RealCall對象
synchronized (this) {
//保證只請求一次
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
//忽略非核心代碼
......
//調用Dispatcher的enqueue方法 ,其中AsyncCall是Runnable。
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
//調用Dispatcher的enqueue方法 ,其中AsyncCall是Runnable。
synchronized void enqueue(AsyncCall call) {
//分別判斷正在執行的異步請求隊列大小 和 正在執行的主機請求隊列大小
if (runningAsyncCalls.size() < 64 && runningCallsForHost(call) < 5) {
//將Runnable添加到正在執行的異步請求隊列
runningAsyncCalls.add(call);
//線程池來執行此Runnable
executorService().execute(call);
} else {
//否則將Runnable添加到正在等待的異步請求隊列
readyAsyncCalls.add(call);
}
}
//Dispatcher類裏面創建線程池,雖然這裏運行的最大線程數爲Integer.MAX_VALUE,
//但是記住前面正在運行的異步隊列大小限制爲64.
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
//作爲Runnable的 AsyncCall,最終的execute()方法爲RealCall裏面的execute()方法。
@Override protected void execute() {
//獲取響應回來的數據response
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
//回調onFailure
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
//回調onResponse
responseCallback.onResponse(RealCall.this, response);
}
......
//線程池執行完線程任務後,調用此方法.
client.dispatcher().finished(this);
}
//作爲Runnable的 AsyncCall,最終的execute()方法爲RealCall裏面的execute()方法。
@Override protected void execute() {
//獲取響應回來的數據response
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
//回調onFailure
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
//回調onResponse
responseCallback.onResponse(RealCall.this, response);
}
......
//線程池執行完線程任務後,調用此方法.
client.dispatcher().finished(this);
}
//client.dispatcher().finished(this)的實現
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
synchronized (this) {
//將任務從隊列中移除
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
//處理就緒狀態的異步請求隊列
if (promoteCalls) promoteCalls();
}
}
//處理就緒狀態的異步請求隊列 promoteCalls() 的實現
private void promoteCalls() {
//遍歷就緒狀態的異步請求隊列readyAsyncCalls
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
if (runningCallsForHost(call) < maxRequestsPerHost) {
//如果滿足條件,則將任務從readyAsyncCalls移除,
//並添加至runningAsyncCalls,然後線程池執行該任務
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
}
}
核心Dispatcher類,維護着線程池executorService,和三個隊列,分別爲就緒狀態的異步請求隊列readyAsyncCalls,運行狀態的異步請求隊列runningAsyncCalls, 運行狀態的同步請求隊列runningSyncCalls。