哈哈,其實寫的仍是很水,各位原諒我O(∩_∩)O。html
介於本身的網絡方面知識爛的一塌糊塗,因此準備寫相關網絡的文章,可是考慮所有寫在一篇太長了,因此分開寫,但願你們能仔細看,最好能夠指出個人錯誤,讓我也能糾正。java
1.講解相關的整個網絡體系結構:web
2.講解相關網絡的重要知識點,好比不少人都聽過相關網絡方面的名詞,可是僅限於聽過而已,什麼tcp ,udp ,socket ,websocket, http ,https ,而後webservice是啥,跟websocket很像,socket和websocket啥關係長的也很像,session,token,cookie又是啥。json
Android技能樹 — 網絡小結(2)之TCP/UDP設計模式
Android技能樹 — 網絡小結(3)之HTTP/HTTPSapi
Android技能樹 — 網絡小結(4)之socket/websocket/webservice數組
相關網絡知識點小結- cookie/session/token(待寫)緩存
3.相關的第三方框架的源碼解析,畢竟如今面試個大點的公司,okhttp和retrofit源碼是必問的。bash
Android技能樹 — 網絡小結(6)之 OkHttp超超超超超超超詳細解析
Android技能樹 — 網絡小結(7)之 Retrofit源碼詳細解析
由於我平時使用的都是Rxjava2 + Retrofit ,因此我相關的源碼解析都是配合RxJava來的,而不是Call返回對象。
讀本文的我推薦你們最好對OKHttp源碼有所瞭解,再來看本文,由於Retrofit內部仍是經過OkHttp發出網絡請求。你們也能夠看我前面寫的:Android技能樹 — 網絡小結之 OkHttp超超超超超超超詳細解析, 同時本文不會再去教你們Retrofit的基礎使用,若是要看一些簡單使用,能夠看下面的一些推薦博客:
Android Retrofit 2.0 的詳細 使用攻略(含實例講解)
Android:Retrofit 結合 RxJava的優雅使用(含實例教程)
咱們先上一張別的大佬博客中的一張圖:
這個圖畫的很好,可是這個圖更多的是從大局觀來看,因此若是對於源碼不是有一些基礎瞭解的話,看這個圖很容易就忘記。
看過個人Okhttp源碼分析的文章:Android技能樹 — 網絡小結之 OkHttp超超超超超超超詳細解析,咱們文中的Okhttp流程圖就是跟着源碼一步步來畫的。我更喜歡是跟着源碼一步步來畫流程圖(PS:實際上是我水平太差了,沒法一會兒總結處第三方庫的各類設計模式的使用),因此Retrofit我也畫了下面這個圖:
而等會咱們分析完這個跟着源碼分析的流程圖後,再回頭看上面的別人博客中的總結的Retrofit結構圖,就會很簡單了。
首先咱們來肯定整體大綱:
咱們知道咱們的目標是要發起一次網絡請求,他有這麼幾步:
X <Y>
,咱們先來看外面的X的類型
,好比咱們常見的返回結果是Call<Y> 和 Observable<Y>
,因此咱們在轉換的時候一是要考慮最外面的那個返回類型的轉換。另一個是Y的類型
,也就是裏面咱們具體寫的Bean對象,好比咱們直接返回字符串,那可能就是Observable<String>
,又或者是本身定義的xxxBean對象,那就是Observable<xxxBean>
。因此咱們要有二類轉換:1.外層的結果類型,好比Call或者Observable等,2.是泛型裏面填的具體的Bean對象類型因此咱們總結起來就須要四步:
沒錯,下次別人問你,你就內心有數了,到底Retrofit作了什麼內容,你就跟別人說很簡單啦,大體作了上面四步,逼格一會兒提升了。。
我這裏直接先把建立Retrofit的對象的代碼寫上:
Retrofit retrofit = new Retrofit.Builder()
.client(new OkHttpClient())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://xxxx.com/")
.build();
複製代碼
不要問建立Retrofit的各自的方法是幹嗎的,咱們後面會一步步講解。
咱們知道咱們日常是這樣寫的:
咱們隨便寫一個常見的獲取某個用戶的我的信息接口來講明:
InfoApi.java:
interface InfoApi{
@GET("userinfo.do")
Observable<UserBean> getInfo(@Query("name") String nameStr);
}
複製代碼
那咱們要拿到:
userinfo.do
= "https://xxxx.com/userinfo.do"
GET請求
name=nameStr
最終咱們發現是GET請求,因此這麼拼在一塊兒:path + "?" + query = http://xxxx/userinfo.do?name=nameStr
因此咱們來看如何一步步拿到相關參數:
咱們知道上面寫的InfoApi.java
是要被retrofit加載進去的:
retrofit.create(InfoApi.class);
複製代碼
因此咱們要來看create
方法的具體操做前,咱們先來了解一下基礎知識,那就是代理模式,若是知道代理模式的,直接能夠忽略此處,直接往下看。
在看create代碼之間,咱們要先學會代理模式相關知識
原本也想一步步長篇大論的寫下,可是後來看到一篇不錯的文章,寫的挺仔細的:java動態代理實現與原理詳細分析 ,但願你們能仔細看完,在看下面的內容。
咱們點進去查看具體的代碼:
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (this.validateEagerly) {
this.eagerlyValidateMethods(service);
}
//'使用了代理模式'
return Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {
private final Platform platform = Platform.get();
public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
} else if (this.platform.isDefaultMethod(method)) {
return this.platform.invokeDefaultMethod(method, service, proxy, args);
} else {
//'咱們能夠看到咱們寫的接口裏面的的method傳入到了loadServiceMethod方法裏面,從而獲得了咱們定義在method上面的相關參數信息。'
ServiceMethod<Object, Object> serviceMethod = Retrofit.this.loadServiceMethod(method);
//'咱們傳入的方法的參數args和上面得到的ServiceMethod,一塊兒傳入OkHttpCall構造函數中,獲得OkHttpCall對象'
OkHttpCall<Object> okHttpCall = new OkHttpCall(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
}
});
}
複製代碼
咱們能夠看到咱們調用的getInfo
這個method方法傳入了:
ServiceMethod<Object, Object> serviceMethod = Retrofit.this.loadServiceMethod(method);
複製代碼
咱們進去查看:
ServiceMethod<?, ?> loadServiceMethod(Method method) {
//'從緩存中去讀'
ServiceMethod<?, ?> result = (ServiceMethod)this.serviceMethodCache.get(method);
if (result != null) {
return result;
} else {
Map var3 = this.serviceMethodCache;
synchronized(this.serviceMethodCache) {
result = (ServiceMethod)this.serviceMethodCache.get(method);
if (result == null) {
//'若是緩存中沒有,則新建'
result = (new retrofit2.ServiceMethod.Builder(this, method)).build();
//'新建完後再放入緩存中'
this.serviceMethodCache.put(method, result);
}
return result;
}
}
}
複製代碼
咱們能夠看到新建的方法:
(new retrofit2.ServiceMethod.Builder(this, method)).build();
複製代碼
咱們來看ServiceMethod類下的Builder的構造函數:
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
//'Java特有的方法,能夠獲取Java方法上面的註解標識,好比:@POST,@GET'
this.methodAnnotations = method.getAnnotations();
//'獲取方法參數裏面定義的參數類型,好比:String,boolean'
this.parameterTypes = method.getGenericParameterTypes();
//'獲取方法裏面的註解標識,好比:@Query,@Path'
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
複製代碼
是否是一會兒就知道了,原來是經過這樣的方式拿到了咱們寫在方法上面的一些參數值,若是還不清楚Method的這幾個方法,能夠看下面的相關連接:
Java獲取類、方法、屬性上的註解
java.lang.reflect.Method.getGenericParameterTypes()方法示例.
使用反射得到參數列表裏的註解getParameterAnnotations.
咱們建立ServiceMethod由於是使用的Builder模式,因此最終要調用build()方法來建立實例:
public ServiceMethod build() {
//'建立了CallAdapter對象,具體幹嗎用的,具體後面會講解'
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ 「 is not a valid response body type. Did you mean ResponseBody?」);
}
//'建立了ResponseConverter對象,具體後面會講解'
responseConverter = createResponseConverter();
//'對於咱們寫的接口請求方法的方法上面的註解進行相關判斷,'
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
//'由於進行方法上面註解的解析了,因此httpMethod的也就相應的被賦值了, 若是爲空,就說明你寫的請求接口方法沒有寫@GET等,就會拋出異常'
if (httpMethod == null) {
throw methodError(「HTTP method annotation is required (e.g., @GET, @POST, etc.).」);
}
//'由於上面解析了,因此好比咱們發現是@GET請求,這時候hasBody會是false,若是你還用了Multipart註解,就會報錯了,他要求是要有request body的,@GET請求是不能使用Multipart的'
if (!hasBody) {
if (isMultipart) {
throw methodError(
「Multipart can only be specified on HTTP methods with request body (e.g., @POST).」);
}
//'同上,表單提交是必定要求有request body的'
if (isFormEncoded) {
throw methodError(「FormUrlEncoded can only be specified on HTTP methods with
+ request body (e.g., @POST).」);
}
}
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
//'遍歷咱們獲取的方法裏面的註解集合,好比@Query,@Path等'
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, 「Parameter type must not include a type variable or wildcard: %s」,
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, 「No Retrofit annotation found.」);
}
//'而後對咱們寫的方法內部參數註解進行判斷,看寫的是否正確等 這裏的判斷很長,好比若是你用的是註解@Body,那麼先判斷你是否用了方法上面的@FormEncode註解或者@Multipart註解, 否則就報錯,而後由於咱們填的參數是對象了,因此內部須要經過RequestBodyConverter來進行轉換,把咱們傳的對象,變成了RequestBody對象。 具體不少不少判斷,各類註解的判斷我都不一一講了,你們只要進去看方法詳細代碼就能夠了。'
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !gotUrl) {
throw methodError(「Missing either @%s URL or @Url parameter.」, httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError(「Non-body HTTP method cannot contain @Body.」);
}
if (isFormEncoded && !gotField) {
throw methodError(「Form-encoded method must contain at least one @Field.」);
}
if (isMultipart && !gotPart) {
throw methodError(「Multipart method must contain at least one @Part.」);
}
return new ServiceMethod<>(this);
}
複製代碼
好,咱們已經成功拿到了咱們的方法中的紅色框出來的部分,綠色的部分咱們尚未獲取。
而代理模式的invoke方法裏面的參數 @Nullable Object[] args,就是咱們具體傳入的參數,好比我這麼寫:
getInfo("青蛙要fly");
複製代碼
args裏面就有了咱們傳入的"青蛙要fly"
字符串。這樣咱們是否是就獲取了上面的其中一個綠色框nameStr的內容了。
咱們拿到包含了這些紅色框參數的ServiceMethod對象後,加上咱們傳入的綠色的框的nameStr的具體的值
,咱們已經能夠進行網絡Request請求的所必要的參數了 (另一個綠色的框只是用來最後網絡請求成功後拿到的Response進行轉換,因此這時候不知道都不影響Request請求)
咱們能夠看到咱們得到到的信息,又用來生成了OkHttpCall對象,而後調用了serviceMethod.adapt(okHttpCall);
方法。
那咱們能夠看到create接下去已經沒有其餘代碼了,因此serviceMethod.adapt(okHttpCall);
確定會幫咱們用剛纔拿到的已知參數,幫咱們拼成Request,完成一次網絡請求。
咱們上面已經說到了進入了serviceMethod.adapt(okHttpCall);
方法了,咱們點進去查看:
T adapt(Call<R> call) {
return callAdapter.adapt(call);
}
複製代碼
咱們能夠看到是調用了callAdapter類的adapt方法。那這個callAdapter對象又是什麼呢?
還記不記得咱們第一大步:建立Retrofit對象時候的代碼:
Retrofit retrofit = new Retrofit.Builder()
.client(new OkHttpClient())
//'這裏傳入了CallAdapterFactory,而Factory類是用來建立具體的CallAdapter對象的工廠類'
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://xxxx.com/")
.build();
複製代碼
因此本文中咱們使用的CallAdapter是RxJava2CallAdapterFactory建立的,咱們先來看ServiceMethod裏面建立CallAdapter的方法:
private CallAdapter<T, R> createCallAdapter() {
//'咱們上面的接口請求方法綠色框裏面的返回類型尚未拿到的,終於在這裏拿到了'
Type returnType = method.getGenericReturnType();
//'若是方法的返回結果包含了泛型表達式、泛型、泛型數組,就拋出異常'
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
「Method return type must not include a type variable or wildcard: %s」, returnType);
}
//'若是方法的返回結果是void,則拋出異常'
if (returnType == void.class) {
throw methodError(「Service methods cannot return void.」);
}
//'咱們前面提過的,獲取方法上的註解,好比@GET等'
Annotation[] annotations = method.getAnnotations();
try {
//'拿着咱們的接口請求方法的返回對象及方法上的註解信息,'
//'去經過Retrofit類的callAdapter類去生成一個CallAdapter對象'
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, 「Unable to create call adapter for %s」, returnType);
}
}
複製代碼
而Retrofit類中的這個callAdapter方法,咱們不看都知道,經過咱們前面建立Retrofit對象時候傳入的addCallAdapterFactory的工廠類來建立具體的CallAdapter,固然咱們具體仍是要具體代碼一步步來看過程。
咱們在調用addCallAdapterFactory加入咱們的RxJava2CallAdapterFactory.create()
,因此先來看下addCallAdapterFactory方法作了什麼:
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
複製代碼
咱們能夠簡單的看到,就是把咱們的Factory工廠類對象加入到private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
這個List隊列中而已。
那這個隊列到底都加了哪些工廠類的,若是我在建立Retrofit對象時候不調用addCallAdapterFactory
方法,難道這個隊列就是空的????那又怎麼去生成CallAdapter對象?
首先確定要加入咱們本身傳入的Factory,有可能一個,也可能傳入多個:
Retrofit retrofit = new Retrofit.Builder()
........
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addCallAdapterFactory(xxxxxxCallAdapterFactory.create())
.addCallAdapterFactory(yyyyyyCallAdapterFactory.create())
........
........
.build();
複製代碼
可是爲了防止咱們創建Retrofit對象時候不調用addCallAdapterFactory傳入本身的Factory,因此自己這個隊列還會加入默認的Factory:
//'看名字就知道,加入平臺的默認的CallAdapterFactory(有java8 和 Android Platform,咱們這裏確定是Android)'
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
複製代碼
固然這個ExecutorCallAdapterFactory確定是繼承了CallAdapter.Factory:
咱們已經知道了咱們的CallAdapterFactory隊列裏面包含了哪些工廠類了。接下來咱們再來具體的Retrofit的callAdapter的方法:
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
//'由於可能有多個CallAdapterFactory工廠類,因此要每一個工廠類都去試一下,有一個成功就直接返回了'
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
int start = callAdapterFactories.indexOf(skipPast) + 1;
//'循環遍歷全部的CallAdapterFactory,而後哪一個能成功生成CallAdapter,就直接返回'
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
//'若是全部的CallAdapterFctory都不能使用,就拼接字符串,拋出異常'
StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
.append(returnType)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
複製代碼
有可能有人會問,爲何CallAdapterFactory有可能生成CallAdapter不成功??還要一個個去遍歷?
由於咱們同時傳入了咱們須要返回的對象的類型傳入到了CallAdapterFactory中,你說若是你是默認的ExecutorCallAdapterFactory
工廠類,你卻傳入了Rxjava的返回相關參數,好比咱們例子中的Observable<UserBean>
,它的代碼裏面都不認識這種返回類型,怎麼幫你去生成對象,並且代碼也是加了判斷,若是返回類型不是Call類型,直接就退出了。
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
//'若是不是Call.class,直接退出生成CallAdapter對象'
if (getRawType(returnType) != Call.class) {
return null;
}
.......
.......
}
複製代碼
因此咱們來看下RxJava2CallAdapterFactory裏面怎麼生成相應的CallAdapter的:
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
//'若是咱們的返回類型是Completable,就直接返回RxJava2CallAdapter對象,裏面的responseType是void'
if (rawType == Completable.class) {
// Completable is not parameterized (which is what the rest of this method deals with) so it
// can only be created with a single configuration.
return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
false, true);
}
//'判斷是不是Flowable或者Single或者Maybe'
boolean isFlowable = rawType == Flowable.class;
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
//'若是既不是上面三種又不是Observable類型,直接返回null'
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}
boolean isResult = false;
boolean isBody = false;
Type responseType;
//'若是不是泛型類的,好比Observable<XXXX> ,則拋異常'
if (!(returnType instanceof ParameterizedType)) {
String name = isFlowable ? "Flowable"
: isSingle ? "Single"
: isMaybe ? "Maybe" : "Observable";
throw new IllegalStateException(name + " return type must be parameterized"
+ " as " + name + "<Foo> or " + name + "<? extends Foo>");
}
//'獲取泛型中的具體參數,好比Observable<xxxBean>中的xxxBean的type'
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
//'獲取xxxBean具體的Class對象'
Class<?> rawObservableType = getRawType(observableType);
//'判斷咱們上面獲取的泛型內容(xxxBean)是否是Response'
if (rawObservableType == Response.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Response must be parameterized"
+ " as Response<Foo> or Response<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
//'判斷咱們上面獲取的泛型內容(xxxBean)是否是Result'
} else if (rawObservableType == Result.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Result must be parameterized"
+ " as Result<Foo> or Result<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
//'咱們日常開發泛型裏面填的確定是本身的Bean對象 //因此最後走的是這裏的代碼'
responseType = observableType;
//'同時isBody設置爲true'
isBody = true;
}
//'生成具體的Rxjava2CallAdapter對象'
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
複製代碼
既然咱們CallAdapter對象也創建完了,咱們回到最剛開始的地方,還記得咱們前面分析的代碼是到了callAdapter.adapt(okHttpCall)
(若是忘記的同窗,能夠從新回頭看下)。
因此咱們如今已經創建的Rxjava2CallAdapter對象了,咱們來看下它的adapt方法:
@Override public Object adapt(Call<R> call) {
/**
'不少人會說這個isAsync,是否異步是哪裏設置的, 其實就是再咱們傳入Factory對象時候創建的。 Retrofit retrofit = new Retrofit.Builder() .client(new OkHttpClient()) 咱們看見建立Factory對象,能夠是createAsync()或者create()方法二種來建立,從而決定是同步仍是異步操做 .addCallAdapterFactory(RxJava2CallAdapterFactory.createAsync()) 或者是 .addCallAdapterFactory(RxJava2CallAdapterFactory.create() .build();'
*/
//'咱們能夠看到上面根據是否異步,創建不一樣的Observable對象,咱們用複雜點的來說解吧, 就當咱們創建的時候使用的是RxJava2CallAdapterFactory.createAsync()方法,因此拿到的對象是CallEnqueueObservable'
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
//'由於咱們Observable<xxxBean>裏面包含的是本身Bean,因此創建的時候isBody = true;'
Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
//'因此咱們的Observable爲BodyObservable'
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
//'因此最終返回了BodyObservable<CallEnqueueObservable>'
return observable;
}
複製代碼
BodyObservable看名字就知道是一個自定義Observable:
final class BodyObservable<T> extends Observable<T> {
private final Observable<Response<T>> upstream;
BodyObservable(Observable<Response<T>> upstream) {
this.upstream = upstream;
}
@Override protected void subscribeActual(Observer<? super T> observer) {
//'當有Observer註冊咱們的Observable的時候, 實際上是咱們前面的傳入的CallEnqueueObservable去註冊了 一個BodyObserver<咱們本身寫的Observer>'
upstream.subscribe(new BodyObserver<T>(observer));
}
}
複製代碼
因此核心仍是咱們傳入的CallEnqueueObservable
這個Observable,因此最後仍是要看這個類的源碼:
final class CallEnqueueObservable<T> extends Observable<Response<T>> {
private final Call<T> originalCall;
CallEnqueueObservable(Call<T> originalCall) {
this.originalCall = originalCall;
}
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
//'咱們能夠看到簡歷了一個CallCallback對象,傳入了用戶寫的咱們前面建立的OkHttpCall對象和用戶寫的observer對象'
CallCallback<T> callback = new CallCallback<>(call, observer);
observer.onSubscribe(callback);
//'而後調用了call的enqueue方法, 由於是OkHttpCall對象,因此咱們直接看OkHttpCall對象的enqueue方法便可'
call.enqueue(callback);
}
private static final class CallCallback<T> implements Disposable, Callback<T> {
.......
.......
.......
}
}
複製代碼
OkHttpCall的enqueue方法:
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
//'建立Okhttp3的Call對象(畢竟最後發起網絡請求是Okhttp,也要使用它的Call對象)'
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
//'常規Okhttp的操做,call.enqueue方法發起異步請求,估計你們都看得懂,我就很少介紹了,咱們直接看拿到返回的數據處理'
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
//'咱們這裏成功的拿到了Okhttp3.Response對象, 因此使用parseResponse方法將rawResponse對象轉換成Retrofit的Response對象'
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
複製代碼
到這裏,咱們已經成功的發送了網絡請求,而且拿到了主句
咱們上面能夠看到咱們是講OkHttp3.Response對象轉換成了Retrofit.Response對象,咱們具體來看下:
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
//'把Okhttp3.Response中的body部分取出來'
ResponseBody rawBody = rawResponse.body();
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
//'咱們就當成功請求回來的,因此code是200'
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
//'核心代碼: 把body部分,經過toResponse方法,變成咱們寫入的泛型(也就是Observable<xxxBean>這個xxxBean對象'
T body = serviceMethod.toResponse(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;
}
}
複製代碼
因此最終咱們發現又回到了serviceMethod裏面了,相關的方法調用都在這裏面:
R toResponse(ResponseBody body) throws IOException {
//'能夠看到咱們經過responseConverter轉換器來對body部分進行了轉換'
return responseConverter.convert(body);
}
複製代碼
這個responseConverter又是怎麼來的呢?咱們再回到建立Retrofit對象的地方:
Retrofit retrofit = new Retrofit.Builder()
.client(new OkHttpClient())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
//'看見了ConverterFactory沒有,就是這裏傳入了咱們的轉換器對象'
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://xxxx.com/")
.build();
複製代碼
咱們來看下具體的代碼:
public final class GsonConverterFactory extends Converter.Factory {
//'能夠看到默認內部使用的是GSON來進行轉換'
public static GsonConverterFactory create() {
return create(new Gson());
}
public static GsonConverterFactory create(Gson gson) {
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
//'這個方法從名字就能夠看出來,是用用來給ResponseBody轉換成咱們要的對象'
@Override
public Converter<ResponseBody, ?> responseBodyConverter(final Type type, Annotation[] annotations, Retrofit retrofit) {
Type newType = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[] { type };
}
@Override
public Type getOwnerType() {
return null;
}
@Override
public Type getRawType() {
return HttpResult.class;
}
};
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(newType));
//'能夠看到,用在Response的轉換器是叫GsonResponseBodyConverter對象'
return new GsonResponseBodyConverter<>(adapter);
}
//'這個名字也能夠看出來是把咱們傳入的對象轉換成RequestBody,從而發起請求'
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations,
Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
//'能夠看到,用在Request的轉換器是叫GsonRequestBodyConverter對象'
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
複製代碼
咱們具體來看看GsonResponseBodyConverter
:
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public T convert(ResponseBody value) throws IOException {
//'根據傳入的ResponseBody獲得JsonReader'
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
//'很簡單,就是GSON進行相關的JSON解析'
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}
複製代碼
這裏咱們看到了既然解析部分是在這裏,是否是咱們能夠作不少定製化操做,答案固然是Yes,好比我寫了個自定義的GsonResponseBodyConverter來進行替換(下面的類就隨便寫寫,你們能夠根據本身的需求寫本身的自定義轉換器):
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, Object> {
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(TypeAdapter<T> adapter) {
this.adapter = adapter;
}
@Override
public Object convert(ResponseBody value) throws IOException {
try {
//'由於我統一的外層對象都是使用的HttpResult,個人代碼是這麼寫的Observable<HttpResult<xxxBean>>'
HttpResult apiModel = (HttpResult) adapter.fromJson(value.charStream());
//'直接在這裏就對統一處理操做'
if (apiModel.getCode().equals(CompanyHttpCode.TOKEN_NOT_EXIST)) {
throw new TokenNotExistException();
} else if (apiModel.getCode().equals(CompanyHttpCode.TOKEN_INVALID)) {
throw new TokenInvalidException();
} else if (!apiModel.getCode().equals(CompanyHttpCode.SUCCESS_CODE)) {
// 特定 API 的錯誤,在相應的 Subscriber 的 onError 的方法中進行處理
throw new ApiException();
} else if (apiModel.getCode().equals(CompanyHttpCode.SUCCESS_CODE) || apiModel.getCode().equals(CompanyHttpCode.SUCCESS_CODE_STR)) {
return apiModel;
}
} finally {
value.close();
}
return null;
}
}
複製代碼
好了,咱們已經拿到了相應的Observable<xxxBean>
裏面的xxxBean對象了,咱們能夠看到:
try {
//'咱們前面講過,經過這個方法轉換的parseResponse(rawResponse); 把OkHttp3.Response轉換成了Retrofit.Response<咱們的bean> '
} catch (Throwable e) {
callFailure(e);
return;
}
try {
//'在轉換成功後,咱們就把具體的response從新經過回調函傳回去給CallEnqueueObservable'
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
複製代碼
CallEnqueueObservable的onResponse方法:
@Override public void onResponse(Call<T> call, Response<T> response) {
if (disposed) return;
try {
//'咱們能夠看到,Observable調用了observerde的onNext方法把Retrofit.Reponse對象發送了出去'
observer.onNext(response);
......
......
......
}
複製代碼
可能有些人就會奇怪了,咱們日常使用,明明拿到的就是具體的裏面的xxxBean對象,而不是Response<xxxBean>
,那是由於上面咱們提過的,咱們的Observer被BodyObserver包了一層:
private static class BodyObserver<R> implements Observer<Response<R>> {
@Override public void onNext(Response<R> response) {
if (response.isSuccessful()) {
//'最終到咱們的Observer的時候,就是Response裏面包含了的咱們寫的xxxBean對象了。'
observer.onNext(response.body());
} else {
.....
.....
}
}
......
......
}
複製代碼
因此如今咱們再來看代碼,是否是已經就能懂中間到底作了什麼操做。哈哈:
interface InfoApi{
@GET("userinfo.do")
Observable<UserBean> getInfo(@Query("name") String nameStr);
}
Retrofit retrofit = new Retrofit.Builder()
.client(new OkHttpClient())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://xxxx.com/")
.build();
retrofit.create(InfoApi.class)
.getInfo("青蛙要fly")
.subscribe(new ResourceObserver<UserBean>() {
@Override
public void onNext(UserBean userBean) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
複製代碼
而後再回頭看這個圖片,是否是也看得懂了:
不知不覺就寫完了,哈哈,可能有些地方不詳細或者是寫的很差又或者是寫錯了。能夠留言,我更但願的是能指出我哪裏寫錯了,哈哈,這樣我也能夠糾正錯誤的知識。