將一個Java接口翻譯成一個Http請求,然后用OkHttp去發送這個請求
一 入口類 Retrofit ? 成員變量
private final ?HttpUrl baseUrl;//網絡請求基地址
private final List<Converter.Factory>converterFactories;//數據轉換器工廠集合
private final List<CallAdapter.Factory>?adapterFactories;//網絡請求適配器工廠集合
private final okhttp3.Call.Factory?callFactory;//底層進行網絡請求工廠
private final Executor?callbackExecutor;//回調方法執行器
/ServiceMethod是對業務接口中方法的注解進行解析之后得到的對象,該對象包含了訪問網絡的除了方法參數值之外的所有必要信息;如數據轉換器、網絡請求適配器、網絡請求工廠、基地址、Http方法等等。
private final Map<Method,ServiceMethod>?serviceMethodCache?=newLinkedHashMap<>();
Retrofit.bulid()方法 初始化 外觀模式
二 動態代理
https://www.ibm.com/developerworks/cn/java/j-lo-proxy1/ 動態代理的機制
http://www.ibm.com/developerworks/cn/java/j-jtp08305.html 動態代理的Decorator
GitHubServiceservice = retrofit.create(GitHubService.class);
create方法就是返回了一個Proxy.newProxyInstance動態代理對象
動態代理是java中的字節碼生成技術。通過接口生成代理類,并將代理類的實現交給InvocationHandler作為具體的實現 ,
動態代理作為 Decorator?
就是你要調用某個class方法的前后 ,你可以很方便的插入些你想要執行的額外代碼
一個動態代理類可以充當所有接口的 Decorator 或 Proxy,這樣就不用每個接口都編寫一個具體的實現類
Call <List<Repo>> repos = service.listRepos("octocat");
執行流程:
service對象其實是一個動態代理對象,并不是一個真正的GitHubService接口的implements產生的對象,當api對象調用listRepos方法時會被動態代理攔截,然后調用Proxy.newProxyInstance方法中的InvocationHandler對象的invoke方法。
invoke方法會傳入3個參數:
Object proxy, 代理對象
Method method,調用的方法 listRepos
Object... args 方法參數 octocat
Retrofit里的動態代理比較巧妙。它不關心proxyd,只是單純的為了拿到了這個method上所有的注解 生成ServiceMethod對象,生成的ServiceMethod對象和args構造生成了HttpCall ?可以發起HTTP請求的類
總結:簡化復雜的網絡請求,通過動態代理的去處理解析與拼裝HTTP請求
三 核心類 ServiceMethod
一個ServiceMethod對象對應于一個 API interface 的一個方法
主要成員變量
final okhttp3.Call.Factory callFactory; //負責創建 HTTP 請求
final CallAdapter callAdapter; //請求適配器? 把retrofit2.Call<T>轉為T
private final Converter responseConverter;? 負責把服務器返回的數據(JSON、XML、二進制或者其他格式,由ResponseBody封裝)轉化為T類型的對象
private final Headers headers; //請求頭信息
private final ParameterHandler[ ] parameterHandlers;//負責解析 API 定義時每個方法的參數,并在構造 HTTP 請求時設置參數
初始化過程 build()方法
callAdapter= createCallAdapter();//將遍歷一個CallAdapter.Factory列表,根據方法返回值類型和注解提供需要的網絡請求適配器
responseType=callAdapter.responseType();
responseConverter= createResponseConverter();//;即根據方法返回值類型和注釋從retrofit中獲取對應的轉換器
for(Annotation annotation :methodAnnotations) {
parseMethodAnnotation(annotation);//解析Method的注解 給ServiceMethod的成員變量賦值
}
for(intp =0;p < parameterCount;p++) {
...
parameterHandlers[p] = parseParameter(p,parameterType,parameterAnnotations);
//方法中的每個參數創建一個ParameterHandler對象,該對象的創建過程就對方法參數中的Body、PartMap、Part、FieldMap、Field等注解進行解析
}
核心:okhttp3.Call.Factory,CallAdapter.Factory和Converter.Factory三個工廠類,模塊之間、類之間通過接口進行依賴,創建十么樣的實現類交給工廠去處理,工廠同樣也是接口,添加怎樣的工廠,則在最初構造Retrofit對象時決定,各個模塊之間完全解耦,每個模塊只負責自己的責任。
四 執行HTTP請求
4.1 OkHttpCall類中execute() 同步發起網絡請求,執行分析
createRawCall() ? ?
1調用了serviceMethod.toRequest(args)來創建okhttp3.Request對象,之前解析參數注解的parameterHandlers在這里給HTTP請求 設置參數傳進入,最后RequestBuilder build()生成Request請求
2 再調用serviceMethod.callFactory.newCall(request)來創建okhttp3.Call,這里之前準備好的callFactory同樣也派上了用場,由于工廠在構造Retrofit對象時可以指定,所以我們也可以指定其他的工廠,來使用其它的底層 HttpClient 實現。這里Retrofit2就和Okhttp結合起來了 網絡請求的執行業務流程都交給Okhttp來處理
return parseResponse(call.execute());
調用okhttp3.Call#execute()來執行網絡請求,這個方法是阻塞的,執行完畢之后將返回收到的響應數據。收到響應數據之后,進行狀態碼的檢查,再調用serviceMethod.toResponse(catchingBody)來把響應數據轉化成我們需要的數據類型對象。使用之前準備好的responseConverte轉化數據。
4.2 enqueue(Callback callback) 異步執行
這里的異步交給了okhttp3.Call#enqueue(Callback responseCallback)來實現,并在它的 callback 中調用parseResponse解析響應數據,并轉發給傳入的 callback
五 ?CallAdapter 接口
請求的適配化OkHttpCall --Adapter--> RxJava/java8/UICallback
通過適配器實現OkHttpCall到其它類型(比如RxJava等第三方庫)的適配轉換
public Interface CallAdapter<T>?{
Type?responseType();//該請求適配器返回的數據類型
?T?adapt(Call call);//該請求適配器對原始Call的再次封裝,如Call到Observable,
abstract class ?Factory?{
public abstract CallAdapter?get(Type?returnType,?Annotation[]?annotations,?Retrofit?retrofit);//獲取網絡請求適配器
protected ? ?staticType?getParameterUpperBound(intindex,?ParameterizedType?type)?
{returnUtils.getParameterUpperBound(index,?type);?}
protectedstaticClass?getRawType(Type?type)?{returnUtils.getRawType(type); }
}
ExecutorCallAdapterFactory 是Retrofit默認實現 ?
該對象存儲一個回調執行器,異步請求將相應的結果交給callbackExecutor回調執行器去執行Android平臺Retrofit2會使用主線程handler構造一個ExecutorCallAdapterFactory,調用enqueue(Callback),callback回調會在主線程中回調
5.1 Retrofit2和RxJava的結合使用
1 RxJavaCallAdapterFactory類?
?RxJava對請求進行包裝,它將根據網絡請求生成一個Observable進行流式任務執行
getCallAdapter方法中對返回值的泛型類型進行了進一步檢查,例如我們聲明的返回值類型為Observable,泛型類型就是List,這里對retrofit2.Response和retrofit2.adapter.rxjava.Result進行了特殊處理,有單獨的 adapter 負責進行轉換,其他所有類型都由SimpleCallAdapter負責轉換
2 SimpleCallAdapter#adapt方法
創建了一個Observable,傳入了CallOnSubscribe類,同時使用了一個OperatorMapResponseToBodyOrError操作符,用來把retrofit2.Response轉為我們聲明的類型,或者錯誤異常類型
3 CallOnSubscribe#call方法
clone 了原來的 call,因為okhttp3.Call是只能用一次的,所以每次都是新 clone 一個進行網絡請求;創建了一個叫RequestArbiter的 producer,把這個 producer 設置給 subscriber;
Producer機制 簡單的理解
Subscriber 都是被動接收 Observable 傳遞 過來的數據,然后Subscriber做處理。
但要是 Observable 發得太多,Subscriber 處理不過來,那就有問題了,所以就有了一種 Subscriber 主動 pull 的機制,而這種機制就是通過 Producer 實現的。給 Subscriber 設置 Producer 之后(通過Subscriber#setProducer方法),Subscriber 就會通過 Producer 向上游根據自己的能力請求數據(通過Producer#request方法),而 Observable 收到請求之后再根據請求的量給 Subscriber 發數據。
RequestArbiter#request方法
執行call.execute() 獲取到Response響應數據,并且發送給下游接收
Observable.lift(OperatorMapResponseToBodyOrError.instance())
lift操作符 負責接收原始的Observable發出的事件,并在response.body()并發送給下游。這里,body()返回的就是我們聲明的泛型類型了
Call<R>->Response<T>->Observable<T> ?執行流程
1 Observable.subscribe,觸發 API 調用的執行;
2 CallOnSubscribe#call,clone call,創建并設置 producer;
3 subscriber 被設置了 producer 之后調用RequestArbiter#request,在 request 中發起網絡請求,把處理結果發給下游;
4 OperatorMapResponseToBodyOrError$1#onNext,把 response 的 ?body 發給下游
5 最終就到了我們 subscribe 時傳入的回調里面了;
六? ? 概括Retrofit2的話,借鑒了服務器編程中AOP思想,利用動態代理技術通過接口在運行時攔截方法,接著通過解析注解拼裝HTTP請求;最后包裝了OkHttpCall生成真正的請求類 發起網絡請求, 通過抽象工廠讓各個模塊直接解耦,完成對原數據Respone的Conver,實現了對Rx、線程的Adapter ,