Retrofit的出現讓Android的網絡請求變得異常簡單,同時能夠很好的配合後臺的REST接口。很是值得咱們去探究一下它的原理。java
一般咱們是Retrofit是和Rxjava配合使用,這裏咱們不作用法上的過多研究,主要看原理,因此下面的代碼都是Retrofit的自身API,沒有用Rxjava。android
下面是一個普通get請求json
新建接口API.java文件:數組
public interface API {
@GET("請求地址,可是不包括服務器的地址")
Call<Response> get( @Query("param1") String param1,//第一個參數 @Query("param2") int param2);//第二個參數
}
複製代碼
在@GET註解裏面加上除去服務器連接的請求地址,@Query註解裏面是請求的參數名。服務器
新建一個單例類,RetrofitService.java(名字隨意),在裏面定義一個靜態的OkHttpClient網絡
private RetrofitService() {//構造方法私有化
}
public static RetrofitService getInstance() {//雙重校驗
if (instance == null) {
synchronized (RetrofitService.class) {
if (instance == null) {
instance = new RetrofitService();
}
}
}
return instance;
}
private static OkHttpClient mOkHttpClient;
private static void initOkHttpClient() {
HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor();//日誌攔截器
mOkHttpClient = new OkHttpClient.Builder().cache(cache)
.addInterceptor(logInterceptor)//日誌攔截器,按照須要添加
.connectTimeout(10, TimeUnit.SECONDS).build();//鏈接超時時間
}
複製代碼
向外提供一個方法,用於獲取剛纔的API接口ide
private volatile static API aPI = null;
public static API createAPI() {
if (aPI == null) {
synchronized (RetrofitService.class) {
if (aPI == null) {
initOkHttpClient();
aPI = new Retrofit.Builder()
.client(mOkHttpClient)
.baseUrl("服務器地址")
.addConverterFactory(GsonConverterFactory.create())//指定json處理庫
.build().create(API.class);//將第一步建立的API接口傳入
}
}
}
return aPI;
}
複製代碼
Call<Response> = call = RetrofitService.getInstance()
.createShowAPI()
.get("參數1", "參數2");
call.enqueue(new Callback<Response>() {
@Override
public void onResponse(Call<Response> call, Response<Response> response) {
//請求成功的處理
}
@Override
public void onFailure(Call<ShowApiResponse<ShowApiNews>> call, Throwable t) {
//請求失敗的處理
}
});
複製代碼
Retrofit是如何將咱們定義的接口方法最後轉化成請求發送出去呢,這裏就到源碼去看看oop
首先來看Retrofit的建立,這裏使用了建立者模式post
new Retrofit.Builder()
.client(mOkHttpClient)
.baseUrl("服務器地址")
.addConverterFactory(GsonConverterFactory.create())//指定json處理庫
.build().create(API.class);//將第一步建立的API接口傳入
複製代碼
首先來看Retrofit.Builder()這個類的構造方法ui
public static final class Builder {
public Builder() {
this(Platform.get());
}
}
複製代碼
這裏調用了一個帶參數的構造方法,先看看Platform.get()是什麼
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
複製代碼
Platform.findPlatform
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
複製代碼
能夠看到,這個Platform類,顧名思義其實就是平臺。在Retrofit中,內置了兩種平臺,一種是Android,一種是Java8。不一樣的平臺,處理的方式不一樣。繼續往下看代碼就明白了
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 {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
複製代碼
這裏先不深刻探究,後面還會再回來,不過咱們已經能夠看到,Executor類在Android平臺裏是返回了MainThreadExecutor,裏面提供了一個handler,而且這個handler是傳入的主線程的Looper,也就是說在execute方法裏面,handler.post其實是在主線程(UI線程)執行的。
這裏再回到Retrofit.Builder(),看看那個帶參數的構造方法:
public Builder() {
this(Platform.get());
}
Builder(Retrofit retrofit) {
platform = Platform.get();
callFactory = retrofit.callFactory;
baseUrl = retrofit.baseUrl;
converterFactories.addAll(retrofit.converterFactories);
adapterFactories.addAll(retrofit.adapterFactories);
// Remove the default, platform-aware call adapter added by build().
adapterFactories.remove(adapterFactories.size() - 1);
callbackExecutor = retrofit.callbackExecutor;
validateEagerly = retrofit.validateEagerly;
}
複製代碼
在這個構造方法裏,對各類屬性進行了初始化,來看看這些屬性的定義
private final Platform platform;//剛纔看到的平臺,這裏是Android
private @Nullable okhttp3.Call.Factory callFactory;//後面在分析
private HttpUrl baseUrl;//服務器地址
private final List<Converter.Factory> converterFactories = new ArrayList<>();//json解析工廠列表
private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();//後面再分析
private @Nullable Executor callbackExecutor;//這裏是Android的Executor,在主線程執行回調
private boolean validateEagerly;//是否提早建立的標誌
複製代碼
挨個看看這幾個屬性,這裏有些屬性的做用咱們後面才知道,不過大部分看命名已經能夠看到一些蹊蹺:主要是callFactory和adapterFactories咱們如今暫時不知道做用,繼續往下看,在構造方法初始化以後,是調用Builder.build()方法
Builder.build()
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
}
複製代碼
在這裏是將Builder的屬性,再傳給Retrofit的構造方法,來看看咱們剛纔疑惑的那兩個屬性怎麼賦值:
callFactory
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
複製代碼
callFactory在默認的狀況下,實際上是一個OkHttpClient,也就是說Retrofit的內部請求原理實際上是用的OkHttp。還記得咱們最開始建立的時候也傳入了一個靜態類OkHttpClient麼,這之間有什麼關係呢?
new Retrofit.Builder().client(mOkHttpClient)
複製代碼
Retrofit.Builder().client
public Builder client(OkHttpClient client) {
return callFactory(checkNotNull(client, "client == null"));
}
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
複製代碼
其實client裏面傳入的OkHttpClient也是賦值給了callFactory,因此callFactory就是OkHttp的網絡請求客戶端
adapterFactories
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
複製代碼
建立了一個新的列表,而且加入了默認的CallAdapterFactory,剛纔咱們知道platform是Android,因此再看看以前的代碼:
Platform.Android
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 {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
複製代碼
defaultCallAdapterFactory返回的是ExecutorCallAdapterFactory
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
}
複製代碼
能夠看到構造方法並無作什麼,只是將回調處理類傳入。裏面的其餘方法後面調用的時候再來看。因此到這裏咱們仍是不知道adapterFactories是幹嗎的,可是咱們看到了這個類裏面有enqueue方法,還有一些處理響應的一些方法,因此咱們能夠知道它的做用是處理請求和響應,具體的用法後面繼續看源碼能夠看到。
在建立者初始化了全部屬性以後,來到了Retrofit.creat方法
aPI = new Retrofit.Builder()
.client(mOkHttpClient)
.baseUrl("服務器地址")
.addConverterFactory(GsonConverterFactory.create())//指定json處理庫
.build().create(API.class);
複製代碼
Retrofit.creat
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);//驗證是否傳入的爲接口類
if (validateEagerly) {//提早建立,默認爲false,這裏跳過
eagerlyValidateMethods(service);
}
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 {
// 方法定義所在的類,這裏咱們是定義在接口裏面,返回false
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//platform.isDefaultMethod沒作任何處理,直接返回false
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
複製代碼
這裏看到了Retrofit的核心,使用動態代理來處理咱們在接口中定義的方法。在調用咱們定義的接口方法時,會來到動態代理類的invoke方法,而後執行最後的三行,在這裏會解析定義的接口方法,而且作相應的處理。
Retrofit在建立的過程當中,有這麼一些東西須要咱們注意
這個是Retrofit支持的平臺,裏面有Android和Java8,這裏天然是Android
執行請求的客戶端,這裏是OkHttpClient,在建立的時候.client傳入
json解析處理工廠數組,這裏是GsonConverterFactory。進行請求和響應的解析,將json字符串轉換爲具體的實體類
請求和響應的具體處理適配器工廠數組,這裏沒有傳的話默認爲ExecutorCallAdapterFactory,若是須要使用rxjava,爲RxJava2CallAdapterFactory
回調處理類,用於對回調數據的處理,這裏是Android平臺默認的MainThreadExecutor,使用Handler在主線程中處理回調。