Retrofit
Retrofit用到了動態(tài)代理;
1.在 retrofit.create(interface service).service是用戶自定義的一個請求數(shù)據(jù)Url相關(guān)的接口(一下同稱自定義請求數(shù)據(jù)接口),這個接口不能繼承其他的接口拒啰。原因如下:
1.進(jìn)入create方法可以看到第一行的代碼如下:
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
這個方法是檢測當(dāng)前這個類是否符合要求。跳進(jìn)去屎媳,代碼如下:
static <T> void validateServiceInterface(Class<T> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// Prevent API interfaces from extending other interfaces. This not only avoids a bug in
// Android (http://b.android.com/58753) but it forces composition of API declarations which is
// the recommended pattern.
if (service.getInterfaces().length > 0) {
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
}
由第一個if語句可知這個類一定要是一個interface绳姨,第二個if語句則限定這個接口不能實現(xiàn)其他的接口佃牛。
1.Converter.Factory 用于創(chuàng)建轉(zhuǎn)換ResponseBody的Converter的工廠類
Converter<T, V>
用于將T轉(zhuǎn)換為V 的轉(zhuǎn)換類荣堰。convert
方法定義了轉(zhuǎn)換的邏輯以及返回了最終轉(zhuǎn)換的結(jié)果床未。
最基本的用法
1. Retrofit retrofit = new Retrofit.Builder()
2. .baseUrl("http://www.baidu.com/")
3. .addConverterFactory(EpgHomePageConverterFactory.create())
4. // .addConverterFactory(GsonConverterFactory.create())
5. .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
6. .build(); //返回一個Retrofit的對象
7. GetResponseService responseService = retrofit.create(GetResponseService.class);
8. //通過動態(tài)代理獲取調(diào)用對應(yīng)的方法,結(jié)合CallAdapter以及ConverterFactory獲取對應(yīng)的Call對象持隧。
Call<EpgHomePage> responseBodyCall = responseService.getResponse("xxxxx","xxxxx",1);
9. //調(diào)用Call的異步網(wǎng)絡(luò)請求即硼,請求網(wǎng)絡(luò)并獲取結(jié)果。
responseBodyCall.enqueue(new Callback<EpgHomePage>() {
@Override
public void onResponse(Response<EpgHomePage> response, Retrofit retrofit) {
Log.i(TAG, response.body().getAreaUrl() + "areaUrl");
}
@Override
public void onFailure(Throwable t) {
}
});
跟蹤上面代碼屡拨,探究Retrofit的工作流程:
-
new Retrofit.Builder()
給Retrofit添加一個默認(rèn)的轉(zhuǎn)換工廠,用于轉(zhuǎn)換網(wǎng)絡(luò)請求的結(jié)果或者生成網(wǎng)絡(luò)請求對象褥实。
public Builder() {
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
}
-
baseUrl("http:/www.baidu.com/xxxx/xxxx/")
根據(jù)字符串參數(shù)呀狼,生成對應(yīng)的HttpUrl。
3.第七句损离,調(diào)用retrofit.create(GetResponseService.class)
方法通過動態(tài)代理模式生成一個GetResponseService的實例哥艇。
4 . loadMethodHandler(method)
用于加載interface中的方法,并構(gòu)建對應(yīng)的網(wǎng)絡(luò)請求url僻澎,Converter以及CallAdapter貌踏。
static MethodHandler<?> create(Retrofit retrofit, Method method) {
CallAdapter<Object> callAdapter = (CallAdapter<Object>) createCallAdapter(method, retrofit);
Type responseType = callAdapter.responseType();
Converter<ResponseBody, Object> responseConverter =
(Converter<ResponseBody, Object>) createResponseConverter(method, retrofit, responseType);
//根據(jù)方法的返回類型以及注釋十饥,構(gòu)成RequestFactory,繼而得到Request對象祖乳。
RequestFactory requestFactory = RequestFactoryParser.parse(method, responseType, retrofit);
return new MethodHandler<>(retrofit, requestFactory, callAdapter, responseConverter);
}
5 . invoke(arg) 傳入方法的參數(shù)逗堵,然后通過OkHttp結(jié)合requestFactory和arg調(diào)用網(wǎng)絡(luò)請求,并且通過responseConverter將請求的結(jié)果轉(zhuǎn)換成對應(yīng)的T.
Object invoke(Object... args) {
return callAdapter.adapt(new OkHttpCall<>(retrofit, requestFactory, responseConverter, args));
}
6.請求網(wǎng)絡(luò)的操作在第九句眷昆,Call<EpgHomePage>
其實是OkHttpCall
對象蜒秤,讓我們來看看enqueue
方法。
@Override public void enqueue(final Callback<T> callback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed");
executed = true;
}
com.squareup.okhttp.Call rawCall;
try {
//獲取一個Call對象 用于網(wǎng)絡(luò)請求
rawCall = createRawCall();
} catch (Throwable t) {
callback.onFailure(t);
return;
}
if (canceled) {
rawCall.cancel();
}
this.rawCall = rawCall;
//執(zhí)行網(wǎng)絡(luò)請求亚斋,傳入一個Okhttp的CallBack作媚,回調(diào)函數(shù)中調(diào)用callback的方法,返回對應(yīng)請求狀態(tài).
rawCall.enqueue(new com.squareup.okhttp.Callback() {
private void callFailure(Throwable e) {
try {
callback.onFailure(e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(response, retrofit);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override public void onFailure(Request request, IOException e) {
callFailure(e);
}
//關(guān)鍵 將請求結(jié)果轉(zhuǎn)換成T類型帅刊。
@Override public void onResponse(com.squareup.okhttp.Response rawResponse) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
});
}
- response = parseResponse(rawResponse);
跳進(jìn)parseResponse(rawResponse)看看是如何實現(xiàn)轉(zhuǎn)換的纸泡。代碼如下:
private Response<T> parseResponse(com.squareup.okhttp.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
//請求失敗
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.readBodyToBytesIfNecessary(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
closeQuietly(rawBody);
}
}
//請求成功
if (code == 204 || code == 205) {
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
//通過調(diào)用ResponseCoverter的converter方法轉(zhuǎn)換。
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
通過以上源碼跟蹤分析:
總結(jié) :
- Converter.Factory<F,T>用于在最后請求的時候赖瞒,將請求得到的結(jié)果轉(zhuǎn)換成F之后再轉(zhuǎn)換成泛型T.
- CallAdapter.Factory 決定了網(wǎng)絡(luò)請求Call適配器弟灼,底層依然是OkhttpCall,不過可以通過自定義Call在OkHttpCall的基礎(chǔ)上進(jìn)行拓展冒黑。對應(yīng)于自定一點的service的接口返回值類型田绑。
Converter.Factory的方法返回CallAdapter<T>。
CallAdapter<T>的Get方法返回 自定義的service的返回值類型抡爹,改類型封裝了Call對象掩驱。responseType 對應(yīng)于函數(shù)的返回值類型。 - 默認(rèn)會設(shè)置HttpClient冬竟,也可以自己設(shè)置HttpClient欧穴。
- 采用動態(tài)代理模式完成請求接口的實例化以及函數(shù)調(diào)用。
- 但是在Retrofit2.0 泵殴,不管請求是否可以轉(zhuǎn)換成功涮帘,onResponse都會被調(diào)用,但是請求返回的結(jié)果不能轉(zhuǎn)換成相應(yīng)的對象笑诅,'response.body()'將返回null调缨,所以記住要處理情況!_耗恪O乙丁!
邊學(xué)習(xí)源碼妇多,邊做的一些隨筆伤哺,寫下來之后有其他理解在不斷完善,有不對的多多指教,歡迎交流立莉。O(∩_∩)O哈绢彤!