### 前言
1.源碼閱讀-整體流程全解析
2.http以及http是原理以及加密過程詳解
[github](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fxiangjiana%2FAndroid-MS)
[面試專題OKhttp詳解1](https://links.jianshu.com/go?to=https%3A%2F%2Fwww.bilibili.com%2Fvideo%2FBV1eK41157jK)
[面試專題OKhttp詳解2](https://links.jianshu.com/go?to=https%3A%2F%2Fwww.bilibili.com%2Fvideo%2FBV1Ea4y147kt)
[面試專題OKhttp詳解終結篇](https://links.jianshu.com/go?to=https%3A%2F%2Fwww.bilibili.com%2Fvideo%2FBV1gZ4y147Gk)
### http協議
第一行:請求行
請求行下面的:請求屬性集
##### 問題一:選擇網絡訪問框架的時候,為什么要選擇OkHttp而不是其他框架;
**明確一點:** 并不期待,你將市面上所有的框架都全部搞得非常清楚,優缺點全部列出來;你是否具備掌控網絡訪問框架的能力;
**這個問題沒有標準答案,最好是帶點主觀意識**
### OkHttp
* **XUtil** 支持網絡請求,圖片加載,甚至還能操作數據庫;就我個人而言,我認為,一個好的網絡訪問框架應該只專注一件事
* **Retrofit** 肯定這個框架不錯,它封裝了OkHttp,所以我暫時沒有去深入了解它,
* **Volley** 官方出品,官方介紹適合小中型app,接口比較多,訪問量比較大;基于HttpUrlConnection封裝,(HttpUrl。。。 android 2.3以下api)
就我個人而言,我更希望能夠更加深入的去了解網絡訪問框架
`OkHttp`基于Socket通信,它更傾向于底層,會對`Http`協議進行完全的封裝,我在學習這個框架的時候,可以更加底層的了解;我相信只要我能搞定`okhttp`,那么其他的訪問框架,都很容易懂;
##### 問題二:OkHttp中為什么使用構建者模式?
使用多個簡單的對象一步一步構建成一個復雜的對象;
* **優點:** 當內部數據過于復雜的時候,可以非常方便的構建出我們想要的對象,并且不是所有的參數我們都需要進行傳遞;
* **缺點:** 代碼會有冗余
##### 問題三:怎么設計一個自己的網絡訪問框架,為什么這么設計?
我目前還沒有正式設計過網絡訪問框架,
**是我自己設計的話,我會從以下兩個方面考慮**
* 先參考現有的框架,找一個比較合適的框架作為啟動點,比如說,基于上面講到的`okhttp`的優點,選擇`okhttp`的源碼進行閱讀,并且將主線的流程抽取出,為什么這么做,因為`okhttp`里面雖然涉及到了很多的內容,但是我們用到的內容并不是特別多;保證先能運行起來一個基本的框架;
* 考慮拓展,有了基本框架之后,我會按照我目前在項目中遇到的一些需求或者網路方面的問題,看看能不能基于我這個框架進行優化,比如服務器它設置的緩存策略,
我應該如何去編寫客戶端的緩存策略去對應服務器的,還比如說,可能剛剛去建立基本的框架時,不會考慮`HTTPS`的問題,那么也會基于后來都要求`https`,進行拓展;
為什么要基于`Okhttp`,就是因為它是基于Socket,從我個人角度講,如果能更底層的深入了解相關知識,這對我未來的技術有很大的幫助;
#### okhttp流程 原理 關鍵類
##### okhttp 關鍵類
~~~csharp
OKHttpClient Request Call-RealCall.enqueue
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
synchronized void enqueue(AsyncCall call) {
當運行的隊列中的數值小于64, 并且同時訪問同一個機器目標HOST請求書小于5直接加入到運行隊列,不然的話就加入到等待隊列
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
Response response = getResponseWithInterceptorChain();
獲取響應的數據
~~~
#### okhttp基本流程

**1: 先搞懂責任鏈是個啥?基于責任鏈搞清楚`reponse` `okhttp`**
**2:搞清楚攔截器**
* 重試/重定向:
* 橋攔截器:封裝header屬性 host keep-live gzip header 進行基本設置,
* 緩存攔截器
* 連接攔截器
* CallServerInterceptor
~~~cpp
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
SynchronousQueue<Runnable> 這個參數是線程池等待隊列,
~~~
> 1:核心線程數 保持在線程池中的線程數量
> 2:線程池最大可容納的線程數
> 3/4參數:當線程池中的線程數量大于核心線程數,空閑線程就會等待60s才會被終止,如果小于就會立刻停止;
#### okhttp完全流程
1:`OkHttpClient okHttpClient = new OkHttpClient.Builder()`
構建一個`okhttpClient`對象,傳入你想傳入的對象,不傳就是默認的;
2:構建request對象
~~~cpp
Request request = new Request.Builder()
~~~
3:`okHttpClient.newCall` 實際上返回的`realCall`類 繼續調用`RealCall.newRealCall`
4:調用`enqueue`方法,傳入我們需要的回調接口,而且會判斷,
~~~java
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
~~~
如果當前這個call對象已經被運行的話,則拋出異常;
5:繼續調用dispatcher的`enqueue`方法,如果當前運行隊列<64并且正在運行,訪問同一個服務器地址的請求<5
就直接添加到運行隊列,并且開始運行;
不然就添加到等待隊列;
6:運行`AsyncCall`,調用它的execute方法
7:在`execute`方法中處理完`response`之后,會在`finally`中調用`dispathcer`的finished方法;
8:當當前已經處理完畢的call從運行隊列中移除掉;并且調用`promoteCalls`方法
9:`promoteCalls`方法中進行判斷,
如果運行隊列數目大于等于64,如果等待隊列里啥都沒有,也直接return?
循環等待隊列,將等待隊列中的數據進行移除,移除是根據運行隊列中還能存放多少來決定;移到了運行隊列中,并且開始運行;
##### 問題四: 如何考慮app的安全性
1:使用https協議進行交互
2:數據交互時,根據業務分出哪些是敏感信息,凡是敏感信息使用對稱加密方式,如果是類似密碼的,則使用不可逆的加密方式;md5
3:考慮跟錢相關,或者同等重要的數據接口,需要做多重驗證,比如:前端加密請求參數,合并請求參數生成MD5碼,服務器端做多重認證,最好能對比本地數據庫或者緩存之類的信息;
4:混淆,
5: app加固,dex文件進行加密,這種方式,可以通過”內存下載“,不安全,也只是為了增加破解難度;
6:將加密算法,一些核心數據添加到so文件中;
鏈接:https://www.jianshu.com/p/f4e353336b86