一、引言
Retrofit 是一個在 Android 和 Java 開發中廣泛使用的類型安全的 HTTP 客戶端。它通過簡潔的 API 設計,使得網絡請求的處理變得高效且易于管理。配置與構建模塊作為 Retrofit 的基礎部分,承擔著初始化和定制 Retrofit 實例的重要任務。開發者可以通過該模塊對 Retrofit 進行多方面的配置,如設置基礎 URL、添加轉換器工廠、適配器工廠等,以滿足不同項目的需求。下面我們將深入到源碼級別,詳細剖析 Retrofit 配置與構建模塊的工作原理。
二、Retrofit 配置與構建的核心類:Retrofit.Builder
2.1 Retrofit.Builder
類概述
Retrofit.Builder
類是 Retrofit 配置與構建的核心類,它提供了一系列的方法用于設置 Retrofit 的各種參數,并最終構建出一個 Retrofit
實例。以下是 Retrofit.Builder
類的部分源碼:
java
public final class Retrofit {// 內部類,用于構建 Retrofit 實例public static final class Builder {// OkHttp 的 Call.Factory 實例,用于創建 HTTP 請求private okhttp3.Call.Factory callFactory;// 基礎 URLprivate HttpUrl baseUrl;// 轉換器工廠列表,用于處理請求和響應的數據轉換private final List<Converter.Factory> converterFactories = new ArrayList<>();// 適配器工廠列表,用于將 Call 對象轉換為其他類型private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();// 回調執行器,用于處理回調操作private Executor callbackExecutor;// 是否提前驗證接口方法private boolean validateEagerly;// 構造函數,初始化默認的轉換器工廠和適配器工廠public Builder() {// 添加默認的轉換器工廠,用于處理基本數據類型的轉換converterFactories.add(new BuiltInConverters());}// 設置 Call.Factory 實例public Builder callFactory(okhttp3.Call.Factory factory) {this.callFactory = checkNotNull(factory, "factory == null");return this;}// 設置基礎 URLpublic Builder baseUrl(String baseUrl) {checkNotNull(baseUrl, "baseUrl == null");// 解析基礎 URL 為 HttpUrl 對象return baseUrl(HttpUrl.get(baseUrl));}// 設置基礎 URLpublic Builder baseUrl(HttpUrl baseUrl) {checkNotNull(baseUrl, "baseUrl == null");// 檢查基礎 URL 是否以 / 結尾List<String> pathSegments = baseUrl.pathSegments();if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);}this.baseUrl = baseUrl;return this;}// 添加轉換器工廠public Builder addConverterFactory(Converter.Factory factory) {converterFactories.add(checkNotNull(factory, "factory == null"));return this;}// 添加適配器工廠public Builder addCallAdapterFactory(CallAdapter.Factory factory) {callAdapterFactories.add(checkNotNull(factory, "factory == null"));return this;}// 設置回調執行器public Builder callbackExecutor(Executor executor) {this.callbackExecutor = checkNotNull(executor, "executor == null");return this;}// 設置是否提前驗證接口方法public Builder validateEagerly(boolean validateEagerly) {this.validateEagerly = validateEagerly;return this;}// 構建 Retrofit 實例public Retrofit build() {if (baseUrl == null) {throw new IllegalStateException("Base URL required.");}okhttp3.Call.Factory callFactory = this.callFactory;if (callFactory == null) {// 如果沒有設置 Call.Factory,默認使用 OkHttpClient 實例callFactory = new OkHttpClient();}Executor callbackExecutor = this.callbackExecutor;if (callbackExecutor == null) {// 如果沒有設置回調執行器,默認使用 Android 主線程執行器callbackExecutor = platform.defaultCallbackExecutor();}// 創建不可變的轉換器工廠列表List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);// 添加默認的轉換器工廠,用于處理字符串和字節數組的轉換converterFactories.add(new BuiltInConverters());// 創建不可變的適配器工廠列表List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);// 添加默認的適配器工廠,用于處理 Call 類型的返回值callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);}}
}
2.2 Retrofit.Builder
類的方法分析
2.2.1 構造函數
java
public Builder() {converterFactories.add(new BuiltInConverters());
}
在構造函數中,會添加一個 BuiltInConverters
實例到轉換器工廠列表中。BuiltInConverters
是一個內置的轉換器工廠,用于處理基本數據類型的轉換。
2.2.2 callFactory
方法
java
public Builder callFactory(okhttp3.Call.Factory factory) {this.callFactory = checkNotNull(factory, "factory == null");return this;
}
該方法用于設置 Call.Factory
實例,Call.Factory
是 OkHttp 中的一個接口,用于創建 Call
對象,Call
對象代表一個 HTTP 請求。這里會對傳入的 factory
進行非空檢查,確保其不為空。
2.2.3 baseUrl
方法
java
public Builder baseUrl(String baseUrl) {checkNotNull(baseUrl, "baseUrl == null");return baseUrl(HttpUrl.get(baseUrl));
}public Builder baseUrl(HttpUrl baseUrl) {checkNotNull(baseUrl, "baseUrl == null");List<String> pathSegments = baseUrl.pathSegments();if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);}this.baseUrl = baseUrl;return this;
}
這兩個重載的 baseUrl
方法用于設置基礎 URL。第一個方法接收一個字符串類型的 baseUrl
,會將其解析為 HttpUrl
對象后調用第二個方法。第二個方法會對 baseUrl
進行檢查,確保其以 /
結尾,否則會拋出 IllegalArgumentException
異常。
2.2.4 addConverterFactory
方法
java
public Builder addConverterFactory(Converter.Factory factory) {converterFactories.add(checkNotNull(factory, "factory == null"));return this;
}
該方法用于添加轉換器工廠到轉換器工廠列表中。轉換器工廠用于創建轉換器,轉換器負責將請求參數序列化為 HTTP 請求體,以及將 HTTP 響應體反序列化為 Java 對象。這里會對傳入的 factory
進行非空檢查。
2.2.5 addCallAdapterFactory
方法
java
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {callAdapterFactories.add(checkNotNull(factory, "factory == null"));return this;
}
該方法用于添加適配器工廠到適配器工廠列表中。適配器工廠用于創建適配器,適配器負責將 Call
對象轉換為其他類型,如 Observable
、Completable
等。這里會對傳入的 factory
進行非空檢查。
2.2.6 callbackExecutor
方法
java
public Builder callbackExecutor(Executor executor) {this.callbackExecutor = checkNotNull(executor, "executor == null");return this;
}
該方法用于設置回調執行器,回調執行器用于處理回調操作。這里會對傳入的 executor
進行非空檢查。
2.2.7 validateEagerly
方法
java
public Builder validateEagerly(boolean validateEagerly) {this.validateEagerly = validateEagerly;return this;
}
該方法用于設置是否提前驗證接口方法。如果設置為 true
,Retrofit 會在創建服務接口實例時對接口方法進行驗證,而不是在調用方法時才驗證。
2.2.8 build
方法
java
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();}List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);converterFactories.add(new BuiltInConverters());List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
build
方法用于構建 Retrofit
實例。在構建過程中,會進行一些必要的檢查和默認值的設置:
- 檢查基礎 URL 是否為空,如果為空則拋出
IllegalStateException
異常。 - 如果沒有設置
Call.Factory
,則默認使用OkHttpClient
實例。 - 如果沒有設置回調執行器,則使用平臺默認的回調執行器。
- 添加默認的轉換器工廠和適配器工廠到相應的列表中。
- 最后使用這些配置創建一個
Retrofit
實例并返回。
三、配置與構建模塊的使用示例
3.1 基本配置
java
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").build();
在這個示例中,我們只設置了基礎 URL,其他配置使用默認值。build
方法會自動處理默認的 Call.Factory
、回調執行器等配置。
3.2 自定義配置
java
OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).build();Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").callFactory(okHttpClient).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).callbackExecutor(Executors.newSingleThreadExecutor()).validateEagerly(true).build();
在這個示例中,我們進行了更詳細的配置:
- 創建了一個自定義的
OkHttpClient
實例,并設置了連接超時、讀取超時和寫入超時時間。 - 使用
callFactory
方法將自定義的OkHttpClient
實例設置為Call.Factory
。 - 使用
addConverterFactory
方法添加了GsonConverterFactory
,用于處理 JSON 數據的轉換。 - 使用
addCallAdapterFactory
方法添加了RxJava2CallAdapterFactory
,用于將Call
對象轉換為 RxJava 的Observable
等類型。 - 使用
callbackExecutor
方法設置了一個單線程的執行器作為回調執行器。 - 使用
validateEagerly
方法設置為提前驗證接口方法。
四、配置與構建模塊的高級用法
4.1 動態配置基礎 URL
在某些情況下,我們可能需要根據不同的環境動態配置基礎 URL。可以通過封裝 Retrofit.Builder
來實現這一點:
java
public class RetrofitClient {private static Retrofit retrofit;public static Retrofit getClient(String baseUrl) {if (retrofit == null) {retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();}return retrofit;}
}
在使用時,可以根據不同的環境傳入不同的基礎 URL:
java
Retrofit retrofit = RetrofitClient.getClient("https://api.example.com/");
4.2 配置攔截器
可以通過自定義 OkHttpClient
并添加攔截器來實現對 HTTP 請求和響應的攔截和處理。以下是一個添加日志攔截器的示例:
java
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;import java.io.IOException;public class RetrofitConfig {public static Retrofit getRetrofit() {// 創建日志攔截器HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);// 創建自定義的 OkHttpClient 并添加攔截器OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(loggingInterceptor).addInterceptor(new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request originalRequest = chain.request();// 可以在這里對請求進行修改,如添加請求頭Request newRequest = originalRequest.newBuilder().header("Authorization", "Bearer your_token").build();return chain.proceed(newRequest);}}).build();return new Retrofit.Builder().baseUrl("https://api.example.com/").callFactory(okHttpClient).addConverterFactory(GsonConverterFactory.create()).build();}
}
在這個示例中,我們添加了一個日志攔截器用于打印請求和響應的詳細信息,還添加了一個自定義的攔截器用于在請求中添加請求頭。
五、配置與構建模塊的異常處理
5.1 基礎 URL 為空異常
在 build
方法中,如果基礎 URL 為空,會拋出 IllegalStateException
異常:
java
if (baseUrl == null) {throw new IllegalStateException("Base URL required.");
}
這是為了確保 Retrofit
實例在構建時必須有一個有效的基礎 URL。
5.2 其他異常
在配置過程中,如果傳入的參數為空,如 callFactory
、converterFactory
、callAdapterFactory
、callbackExecutor
等,會在相應的設置方法中拋出 NullPointerException
異常,因為這些方法都進行了非空檢查:
java
public Builder callFactory(okhttp3.Call.Factory factory) {this.callFactory = checkNotNull(factory, "factory == null");return this;
}
六、配置與構建模塊的性能優化
6.1 單例模式
為了避免重復創建 Retrofit
實例,可以使用單例模式。以下是一個簡單的單例實現:
java
public class RetrofitSingleton {private static Retrofit retrofit;private RetrofitSingleton() {}public static synchronized Retrofit getInstance() {if (retrofit == null) {retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();}return retrofit;}
}
使用單例模式可以減少內存開銷,提高性能。
6.2 合理配置 OkHttpClient
OkHttpClient
是 Retrofit 底層使用的 HTTP 客戶端,合理配置 OkHttpClient
可以提高性能。例如,可以設置連接池、緩存等:
java
OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).connectionPool(new ConnectionPool(5, 5, TimeUnit.MINUTES)).cache(new Cache(cacheDirectory, cacheSize)).build();
在這個示例中,我們設置了連接超時、讀取超時和寫入超時時間,還設置了連接池和緩存。連接池可以復用已經建立的連接,減少連接建立的開銷;緩存可以避免重復的網絡請求,提高響應速度。
七、配置與構建模塊的未來發展趨勢
7.1 與更多的 HTTP 客戶端集成
目前 Retrofit 主要與 OkHttp 集成,未來可能會支持更多的 HTTP 客戶端,如 HttpURLConnection 等,以滿足不同開發者的需求。
7.2 更簡潔的配置方式
隨著 Android 開發的不斷發展,可能會出現更簡潔的配置方式,減少開發者的配置工作量。例如,通過注解或配置文件來進行配置。
7.3 更好的性能優化
未來的配置與構建模塊可能會進行更多的性能優化,如減少初始化時間、降低內存開銷等。可以通過優化內部的數據結構和算法來實現這些優化。
7.4 增強的錯誤處理和調試功能
配置與構建模塊可能會提供更詳細的錯誤信息和調試工具,幫助開發者更快地定位和解決問題。例如,在異常信息中提供更多的上下文信息,或者提供可視化的調試工具。
八、總結
Retrofit 的配置與構建模塊是整個框架的基礎,它提供了豐富的配置選項,使得開發者可以根據不同的需求對 Retrofit 進行定制。通過深入分析 Retrofit.Builder
類的源碼,我們了解了各個配置方法的作用和實現細節。在實際開發中,我們可以根據項目的需求進行合理的配置,如設置基礎 URL、添加轉換器工廠和適配器工廠、配置攔截器等。同時,我們還可以通過單例模式和合理配置 OkHttpClient
來提高性能。隨著 Android 開發的不斷發展,配置與構建模塊也可能會不斷改進和完善,為開發者提供更好的開發體驗。