咱們先來看一下Retrofit的常見使用方法:git
//建立網絡請求接口類 public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); } //建立Retrofit實例對象 Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build(); //經過動態代理建立網絡接口代理對象 GitHubService service = retrofit.create(GitHubService.class); //獲取Call對象 Call<List<Repo>> repos = service.listRepos("octocat"); //執行同步請求或異步請求 repos.execute(); repos.enqueue(callback)
上面是Retrofit的最基本使用方法,固然如今使用最多的仍是RxJava2+Retrofit搭配使用,關於RxJava2,你們能夠看個人另外一篇 RxJava2源碼分析 ,固然RxJava2與Retrofit搭配使用的解析我會在稍後分析,這裏咱們先關注最基本的使用方法。github
這一步的目的就是封裝咱們網絡請求相關的一些參數,沒什麼好多說的。設計模式
Retrofit實例對象的建立很明顯是採用了Builder模式,Builder模式在 Java語言中 建立一個 有不少可選配置參數 的對象的時候是很好的一種設計模式。Builder模式有兩個重點,一個是在 Java語言中 中,另外一個是 有不少可選配置參數,其實在如今的Android開發中,使用Kotlin開發Android已經很廣泛了,熟悉Kotlin語法的小夥伴可能很熟悉了,因爲Kotlin中 默認參數 的存在,因此在Kotlin中使用Builder模式的意義不大。但因爲Java語法的限制,在建立一個 有不少可選配置參數 的時候,Builder模式仍是首要選擇。api
咱們來看一下Retrofit中的成員變量:緩存
public final class Retrofit { //緩存封裝好的ServiceMethod private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>(); //OKHttp中的網絡請求工廠 final okhttp3.Call.Factory callFactory; //BaseUrl final HttpUrl baseUrl; //數據轉換器工廠集合 final List<Converter.Factory> converterFactories; //網絡請求適配器工廠集合 final List<CallAdapter.Factory> callAdapterFactories; //處理線程切換 final @Nullable Executor callbackExecutor; //不須要關注,默認爲false final boolean validateEagerly; //忽略無關代碼...... }
serviceMethodCache 是一個HashMap,它的Key是Method,表明咱們定義的網絡請求接口類中的方法,它的Value是ServiceMethod,表明對網絡請求接口類中的方法的一個封裝,簡單看一下它就明白了:網絡
final class ServiceMethod<R, T> { private final okhttp3.Call.Factory callFactory; private final CallAdapter<R, T> callAdapter; private final HttpUrl baseUrl; private final Converter<ResponseBody, R> responseConverter; private final String httpMethod; private final String relativeUrl; private final Headers headers; private final MediaType contentType; private final boolean hasBody; private final boolean isFormEncoded; private final boolean isMultipart; private final ParameterHandler<?>[] parameterHandlers; //忽略無關代碼....... }
很明顯了,ServiceMethod就是對網絡請求參數的封裝類,包含請求頭、相對url、GET請求或者是POST請求等等對請求的配置信息。serviceMethodCache 就是一個對ServiceMethod的緩存,能夠提升必定的效率。框架
在Retrofit中,默認的數據轉換器工廠就是 GsonConverterFactory ,因此其實若是咱們是使用 Gson 來作數據轉換的,其實沒有必要去配置。在Android平臺,Retrofit中默認的網絡請求適配器工廠是 ExecutorCallAdapterFactory ,咱們簡單瞅一眼它是如何被建立的:異步
static class Android extends Platform { @Override public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); } @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { if (callbackExecutor == null) throw new AssertionError(); return new ExecutorCallAdapterFactory(callbackExecutor); } static class MainThreadExecutor implements Executor { //注意這裏建立了一個位於主線程的Handler private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { //經過handler.post(runnable)實現線程切換 handler.post(r); } } }
能夠看到,在建立 ExecutorCallAdapterFactory 的同時傳入了一個 callbackExecutor ,這個 callbackExecutor 也是Retrofit中默認的 callbackExecutor ,在Android平臺中它是 MainThreadExecutor類型 ,能夠看到,在它的內部建立了一個位於主線程的Handler。咱們知道,使用Retrofit的時候不一樣於直接使用OKHttp,在使用Retrofit的異步網絡請求時,網絡結果的回調是位於主線程中的,那麼Retrofit是如何切換的線程,看過上面的代碼應該會內心有個數了,它是經過 handler.post(r) 來實現由子線程到主線程的切換。ide
看過個人Retrofit源碼分析第二篇:代理模式的小夥伴們應該都比較清楚了,在Retrofit的 create 方法中實際上是使用了動態代理生成了一個代理對象,如今咱們就來看一下 create 的源碼:oop
public <T> T create(final Class<T> service) { //忽略無關代碼...... //下面就是JDK給咱們提供的動態代理了 return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { //忽略無關代碼...... //獲取method的網絡請求參數的封裝類ServiceMethod對象 ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); //獲取對OKHttp中的RealCall的一個包裝類OkHttpCall對象 OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); //經過網絡請求適配器將原始的Call對象轉換成須要的對象,好比RxJavaCallAdapter會將Call對象轉換成Observable。 return serviceMethod.adapt(okHttpCall); } }); }
在 create 方法中作了3件事:
封裝網絡請求方法很容易理解,關於ServiceMethod上面已經說過,再也不贅述。封裝原始Call對象,對OKHttp源碼熟悉的小夥伴應該知道,原始的Call其實就是OkHttp中的ReallCall。若是不熟悉OkHttp的同窗能夠看我以前的一篇 OkHttp源碼分析 。咱們能夠簡單看一下這個包裝類 OkHttpCall :
final class OkHttpCall<T> implements Call<T> { //忽略無關代碼...... @Override public Response<T> execute() throws IOException { okhttp3.Call call; //熟悉OkHttp源碼的同窗應該很熟悉了,徹底照抄OkHttp中的代碼,確保每一個Call只會被執行一次 synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; //忽略無關代碼...... call = rawCall; if (call == null) { try { //建立OkHttp中的RealCall對象 call = rawCall = createRawCall(); } catch (IOException | RuntimeException | Error e) { throwIfFatal(e); // Do not assign a fatal error to creationFailure. creationFailure = e; throw e; } } } if (canceled) { call.cancel(); } //解析OkHttp中的RealCall執行同步方法後返回的網絡數據 return parseResponse(call.execute()); } @Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); okhttp3.Call call; Throwable failure; //確保一個Call對象只被執行一次 synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; call = rawCall; failure = creationFailure; if (call == null && failure == null) { try { //建立OkHttp中的RealCall對象 call = rawCall = createRawCall(); } catch (Throwable t) { throwIfFatal(t); failure = creationFailure = t; } } } if (failure != null) { callback.onFailure(this, failure); return; } if (canceled) { call.cancel(); } //調用OkHttp中的RealCall的異步請求網絡方法 call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) { Response<T> response; try { 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(); } } }); } }
能夠看到,Retrofit中的這個 OKHttpCall 徹底是對OkHttp中的 RealCall 的一個包裝。在 OKHttpCall 中的同步網絡方法 execute 和異步網絡方法 enQueue 中其實就作了三件事:獲取 RealCall 對象,調用 RealCall 中的 execute 或者 enQueue 方法,而後去解析OkHttp返回的原始數據並轉換成咱們須要的類型,就這麼簡單。
接下來就 create 方法中就只剩下 經過CallAdapter轉換Call對象 了,咱們上面說過,在沒有特別配置CallAdapter的時候,默認的CallAdapterFactory是 ExecutorCallAdapterFactory ,很明顯,CallAdapter是由Factory建立的,那咱們看一下這個默認的CallAdapterFactory:
final class ExecutorCallAdapterFactory extends CallAdapter.Factory { //本質是傳入的MainThreadExecutor final Executor callbackExecutor; ExecutorCallAdapterFactory(Executor callbackExecutor) { this.callbackExecutor = callbackExecutor; } @Override public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != Call.class) { return null; } final Type responseType = Utils.getCallResponseType(returnType); //直接建立並返回一個CallAdapter的匿名對象 return new CallAdapter<Object, Call<?>>() { @Override public Type responseType() { return responseType; } @Override public Call<Object> adapt(Call<Object> call) { //返回默認的CallAdapter轉換後的Call對象 return new ExecutorCallbackCall<>(callbackExecutor, call); } }; } static final class ExecutorCallbackCall<T> implements Call<T> { //本質是傳入的MainThreadExecutor final Executor callbackExecutor; //就是OKHttpCall,從名字也能理解,代理Call對象 final Call<T> delegate; ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) { this.callbackExecutor = callbackExecutor; this.delegate = delegate; } @Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); //調用OkHttp中RealCall的異步網絡請求 delegate.enqueue(new Callback<T>() { @Override public void onResponse(Call<T> call, final Response<T> response) { //注意,OkHttp的異步回調是在子線程的,Retrofit這裏實現了線程的切換,本質是調用了handler.post(runnable) callbackExecutor.execute(new Runnable() { @Override public void run() { if (delegate.isCanceled()) { callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled")); } else { callback.onResponse(ExecutorCallbackCall.this, response); } } }); } @Override public void onFailure(Call<T> call, final Throwable t) { //注意,OkHttp的異步回調是在子線程的,Retrofit這裏實現了線程的切換,本質是調用了handler.post(runnable) callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallbackCall.this, t); } }); } }); } @Override public boolean isExecuted() { return delegate.isExecuted(); } @Override public Response<T> execute() throws IOException { //因爲同步方法不須要切線程,因此直接執行並返回OKHttpCall的同步網絡方法 return delegate.execute(); } @Override public void cancel() { delegate.cancel(); } @Override public boolean isCanceled() { return delegate.isCanceled(); } @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone. @Override public Call<T> clone() { return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone()); } @Override public Request request() { return delegate.request(); } } }
上面的代碼其實也很清晰了 ExecutorCallAdapterFactory 這個CallAdapter工廠類直接建立並返回一個CallAdapter的匿名對象,這個其實就是咱們Retrofit的默認CallAdapter,關鍵是這個CallAdapter的adapt方法,它返回了 ExecutorCallbackCall 這個對OkHttpCall的包裝類,咱們關注這個包裝類的 enqueue 方法,在這個方法中,它經過調用 callbackExecutor.execute
來實現了子線程到主線程的線程切換。這個 callbackExecutor 就是 MainThreadExecutor ,這個類咱們上面提到過, MainThreadExecutor 中的 execute 方法內部就是 handler.post(r);
,這個 handler 其實就是主線程的,所以實現了線程切換。
其實通過上一步的分析,咱們已經知道了,咱們獲取的Call對象,實際上是經過動態代理中 serviceMethod.adapt(okHttpCall)
返回的Call對象,這個其實就是 ExecutorCallbackCall ,這個咱們都很清楚了,它是對OkHttp中RealCall的一個包裝類,在它的異步方法中經過調用 callbackExecutor.execute
實現了線程的切換,固然本質仍是經過 Handler 機制。
其實到此爲止,基本的流程已經分析完畢了,咱們到這裏也會很清楚Retrofit的定位:Retrofit並非一個網絡請求的框架,而是一封裝網絡請求參數,解析網絡返回結果的框架。下面咱們來分析一下使用了RxJava2CallAdapter的狀況。
CallAdapter的重點是它的adapt方法,咱們來看一下RxJava2CallAdapter中的adapt方法:
@Override public <R> Object adapt(Call<R> call) { //建立一個發射網絡返回結果的Observable Observable<Response<R>> responseObservable = new CallObservable<>(call); Observable<?> observable; if (isResult) { observable = new ResultObservable<>(responseObservable); } else if (isBody) { observable = new BodyObservable<>(responseObservable); } else { observable = responseObservable; } //默認scheduler爲空 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(); } return observable; }
這段代碼本質是建立一個發射網絡返回結果的Observable,咱們看一下 CallObservable 的內部實現,看過RxJava2源碼的同窗應該都知道,Observable的關鍵方法是 subscribeActual,咱們就看一下這個方法內部都作了什麼:
@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(); observer.onSubscribe(new CallDisposable(call)); boolean terminated = false; try { //調用了OKHttpCall的同步網絡訪問方法,並獲取網絡數據 Response<T> response = call.execute(); if (!call.isCanceled()) { //將獲取到的網絡數據發送到觀察者observer observer.onNext(response); } if (!call.isCanceled()) { terminated = true; //發送結束事件 observer.onComplete(); } } catch (Throwable t) { Exceptions.throwIfFatal(t); if (terminated) { RxJavaPlugins.onError(t); } else if (!call.isCanceled()) { try { //發送錯誤事件 observer.onError(t); } catch (Throwable inner) { Exceptions.throwIfFatal(inner); RxJavaPlugins.onError(new CompositeException(t, inner)); } } } }
熟悉RxJava2的同窗看完就應該懂了:RxJava2CallAdapter經過adapt方法生成並返回一個 CallObservable 對象,在這個 CallObservable 內部通調用 OKHttpCall 的 execute() 方法進行網絡訪問,並將獲取到的數據發送到下一級的觀察者observer中。
到此爲止,Retrofit的源碼分析終於結束了,其實它並不難,但想要徹底理解整個網絡訪問流程,除了要明白Retrofit,還須要瞭解OKHttp甚至是RxJava,對後二者不太熟悉的小夥伴們能夠看個人另外兩篇源碼分析:OkHttp源碼分析 , RxJava2源碼分析 ,在熟悉了OKHttp和RxJava2的基礎上再回過頭來看Retrofit,相信你會有更深的理解。