一、okHttp的同步和異步請求
Call?是 OkHttp 的核心接口,代表一個已準備好執行的 HTTP 請求。它支持?同步?和?異步?兩種模式:
? ? ? ? enqueue——>okHttp異步
OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("https://example.com").build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onResponse(Call call, Response response) throws IOException {System.out.println("Response: " + response.body().string());}@Overridepublic void onFailure(Call call, IOException e) {System.err.println("Request failed: " + e.getMessage());}
});
????????execute——>同步請求
? ? ? ? 特點
-
阻塞線程
請求發送后,當前線程會阻塞,直到服務器返回響應或超時。 -
直接返回結果
通過?execute()
?方法直接返回?Response
?對象,無需回調。 -
線程管理
不能在主線程中執行,否則會觸發?NetworkOnMainThreadException
?異常。同步請求必須在后臺線程中執行,可以使用?Thread
、ExecutorService
?或 RxJava 等工具管理線程。 -
資源釋放
Response
?對象實現了?Closeable
?接口,使用?try-with-resources
?語法確保資源釋放。 -
超時設置
默認超時為 10 秒,可通過?OkHttpClient.Builder
?自定義:
OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("https://example.com").build();
try (Response response = client.newCall(request).execute()) {if (response.isSuccessful()) {System.out.println("Response: " + response.body().string());} else {System.err.println("Request failed: " + response.code());}
} catch (IOException e) {System.err.println("Request error: " + e.getMessage());
}
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {try (Response response = client.newCall(request).execute()) {if (response.isSuccessful()) {System.out.println
特性 | 同步請求(execute ) | 異步請求(enqueue ) |
---|---|---|
線程阻塞 | 阻塞當前線程,直到請求完成 | 不阻塞線程,后臺執行 |
結果獲取 | 直接返回?Response ?對象 | 通過?Callback ?回調處理結果 |
線程管理 | 需手動管理線程,避免主線程阻塞 | 自動在后臺線程執行,主線程無影響 |
適用場景 | 需立即獲取結果的場景(如單元測試) | 需異步處理的場景(如網絡請求) |
二、okHttp+Rxjava
Observable<Response> observable = Observable.create(emitter -> {Call call = client.newCall(request);call.enqueue(new Callback() {@Overridepublic void onResponse(Call call, Response response) {if (!emitter.isDisposed()) {emitter.onNext(response);emitter.onComplete();}}@Overridepublic void onFailure(Call call, IOException e) {if (!emitter.isDisposed()) {emitter.onError(e);}}});emitter.setCancellable(call::cancel);
});observable.subscribeOn(Schedulers.io()) // 在 IO 線程執行.observeOn(AndroidSchedulers.mainThread()) // 在主線程處理結果.subscribe(new Observer<Response>() {@Overridepublic void onSubscribe(Disposable d) {// 訂閱時調用}@Overridepublic void onNext(Response response) {System.out.println("Response: " + response.body().string());}@Overridepublic void onError(Throwable e) {System.err.println("Error: " + e.getMessage());}@Overridepublic void onComplete() {// 請求完成時調用}});
二、Retrofit 的同步與異步用法,用Call發起請求
Retrofit 內部使用 OkHttp 作為 HTTP 客戶端,這意味著在 Retrofit 的配置中,你可以定制 OkHttp 的各種參數(如超時設置、攔截器等)。
為了更好地支持異步編程,Retrofit 提供了 RxJava 的 CallAdapter。通過這個適配器,你可以讓 API 接口直接返回 Observable、Single 等 RxJava 類型,從而使用 RxJava 的強大操作符來處理請求結果和錯誤。
public interface ApiService {@GET("users")Call<List<User>> getUsers();
}
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").addConverterFactory(GsonConverterFactory.create()) // 使用 Gson 進行 JSON 轉換.build();ApiService apiService = retrofit.create(ApiService.class);
Retrofit同步請求
????????需在子線程中調用,否則會觸發?NetworkOnMainThreadException
new Thread(new Runnable() {@Overridepublic void run() {try {Call<List<User>> call = apiService.getUsers();Response<List<User>> response = call.execute();if (response.isSuccessful() && response.body() != null) {List<User> users = response.body();// 處理返回的數據} else {Log.e("Retrofit", "Response error: " + response.code());}} catch (IOException e) {e.printStackTrace();}}
}).start();
Retrofit異步請求
Call<List<User>> call = apiService.getUsers();
call.enqueue(new Callback<List<User>>() {@Overridepublic void onResponse(Call<List<User>> call, Response<List<User>> response) {if (response.isSuccessful() && response.body() != null) {List<User> users = response.body();// 處理返回的數據,比如更新 UI} else {// 請求成功,但是服務器返回錯誤碼,比如 404、500 等Log.e("Retrofit", "Response error: " + response.code());}}@Overridepublic void onFailure(Call<List<User>> call, Throwable t) {// 請求失敗,比如網絡錯誤或解析錯誤Log.e("Retrofit", "Request failed", t);}
});
三、Retrofit + RxJava 的同步/異步與線程統一處理,用Observable發起請求
Observable?是 RxJava 的響應式編程模型,用于處理異步數據流。其優勢包括:
- 鏈式調用:通過操作符(如?
map
、flatMap
)簡化復雜邏輯。 - 線程調度:通過?
subscribeOn
?和?observeOn
?控制線程切換。 - 錯誤處理:通過?
onErrorReturn
?或?retry
?實現容錯。
同步請求
public interface ApiService {@GET("users/{id}")Observable<User> getUserRx(@Path("id") int id); // 返回 Observable
}apiService.getUserRx(1).subscribeOn(Schedulers.io()) // 指定請求線程.observeOn(Schedulers.io()) // 指定響應處理線程.blockingSubscribe(user -> {// 同步阻塞獲取結果});
異步請求
// 1. 定義 API 接口,使用 RxJava 的 Observable 作為返回類型
public interface ApiService {@GET("users")Observable<List<User>> getUsers();
}// 2. 配置 OkHttp 客戶端(可添加攔截器、日志打印等)
OkHttpClient okHttpClient = new OkHttpClient.Builder()// 例如:添加日志攔截器// .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)).build();// 3. 配置 Retrofit,同時添加 Gson 轉換器和 RxJava 適配器
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").client(okHttpClient).addConverterFactory(GsonConverterFactory.create()) // JSON 數據解析.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // RxJava 適配器.build();// 4. 創建 API 服務實例
ApiService apiService = retrofit.create(ApiService.class);// 5. 使用 RxJava 進行網絡請求
apiService.getUsers().subscribeOn(Schedulers.io()) // 在 IO 線程執行網絡請求.observeOn(AndroidSchedulers.mainThread()) // 在主線程處理返回結果.subscribe(users -> {// 成功回調,處理用戶數據}, throwable -> {// 錯誤回調,處理異常情況});
方案 | 線程管理 | 代碼復雜度 | 適用場景 |
---|---|---|---|
OkHttp 原生 | 手動切換 | 低 | 簡單請求、低耦合場景 |
Retrofit 原生 | 手動切換 | 中 | 接口化請求、中等復雜度 |
Retrofit+RxJava | 自動統一管理 | 高 | 復雜異步流、高可維護性 |
四、具體使用Retrofit+RxJava
// 1. 定義服務接口
public interface UserService {@POST("/user/{userId}/profile")Observable<BaseResponse<UserProfile>> updateProfile(@Path("userId") String userId,@Body ProfileParams params);
}// 2. 發起請求
NetworkApi.createService(UserService.class, ServiceType.User.name()).updateProfile("123", new ProfileParams("Kimi", "avatar.jpg")).compose(NetworkApi.applySchedulers()).subscribe(new BaseObserver<UserProfile>() {@Overridepublic void onSuccess(UserProfile profile) {// 更新UI}@Overridepublic void onBusinessError(int code, String msg) {// 顯示錯誤提示}});
設計優勢:
- 責任鏈模式:每個方法專注單一職責(創建→配置→調度→響應)
- 類型安全:通過泛型確保數據模型一致性
- 異常隔離:BaseObserver集中處理網絡/業務異常
- 線程透明:applySchedulers()隱藏線程切換細節
該模式常見于需要支持多環境、多服務類型的現代移動應用架構,特別適合企業級應用開發中需要統一管理API請求的場景。
這是典型的Retrofit+RxJava組合的網絡請求鏈式調用寫法,結合了工廠模式、建造者模式和響應式編程思想。其核心結構可分為四個關鍵部分:
1.服務實例創建
NetworkApi.createService(ApiService.class, ServiceType.License.name())
NetworkApi
是自定義的工廠類,封裝了Retrofit實例的創建過程createService()
方法通過動態代理生成ApiService接口的實現類ServiceType.License.name()
指定服務類型,通常用于動態配置baseUrl(如區分認證服務、業務服務等)
2.具體API操作
.action(id, params)
action()
對應ApiService接口中定義的端點方法:
@POST("/api/{serviceType}/actions")
Observable<BaseResponse<T>> action(@Path("serviceType") String serviceType,@Body ActionParams params
);
id
參數可能用于路徑替換(@Path注解),params
作為請求體(@Body注解)
3.線程調度組合
.compose(NetworkApi.applySchedulers(...))
compose()
是RxJava的操作符,統一應用線程切換規則applySchedulers()
典型實現:
4.觀察者封裝
new BaseObserver<BaseResponse<AccessConsentRecordDetailBean>>()
- 自定義的BaseObserver處理通用邏輯:
public abstract class BaseObserver<T> implements Observer<T> {@Overridepublic void onError(Throwable e) {// 統一錯誤處理(網絡異常、業務異常等)}@Overridepublic void onNext(T response) {if (response.isSuccess()) {onSuccess(response.getData());} else {onBusinessError(response.getCode(), response.getMessage());}}
}
五、Flowable與Observable
Flowable與Observable是RxJava中兩種核心的響應式數據流類型,結合Retrofit使用時需要根據具體場景進行選型。以下是兩者的核心區別及在Retrofit中的實踐建議:
類型 | 特性 | Retrofit集成場景 |
---|---|---|
Observable | 無背壓機制的異步數據流,支持同步/異步操作,適合輕量級請求 | 簡單API調用(如獲取用戶信息、配置數據) |
Flowable | 支持背壓控制的響應式流,內置5種策略處理生產消費速度差異 | 大文件傳輸、實時數據推送等高并發場景 |
核心區別
1.?背壓處理機制
- Flowable
通過BackpressureStrategy
配置策略(ERROR/BUFFER/DROP/LATEST/MISSING),在Retrofit中處理大數據流時需顯式指定策略:
@GET("api/sensor-data")
Flowable<Data> getSensorData(@Query("deviceId") String id); // 默認使用ERROR策略[5](@ref)
- Observable
無背壓控制,Retrofit接口直接返回Observable時需確保數據量可控,否則可能引發OOM
2.?線程模型
Flowable
強制異步訂閱,Retrofit需配合subscribeOn(Schedulers.io())
使用:
api.getSensorData("DEV001").subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
Observable
支持同步調用,適合快速響應的本地緩存查詢:
@GET("api/profile")
Observable<User> getUserProfile(); // 同步獲取用戶數據[9](@ref)
3.?性能表現
- Flowable
因背壓檢測機制,吞吐量比Observable低約15-30%,但內存更安全 - Observable
無額外性能損耗,適合高頻低數據量請求(如按鈕點擊事件統計)
4.集成實現
- BUFFER:文件下載(需注意內存監控)
Flowable.create(emitter -> {...}, BackpressureStrategy.BUFFER)
- DROP:實時股票行情推送(丟棄過時數據)
- LATEST:即時聊天消息(保留最新消息)
5.錯誤處理對比
- Observable需手動捕獲異常:
.subscribe(data -> {...},error -> { // 需處理所有異常 }
)
- Flowable通過
onBackpressureXXX
操作符自動處理:
.onBackpressureDrop(dropped -> log("丟棄數據:" + dropped))
性能優化建議
-
混合使用策略
對核心業務接口使用Flowable+BUFFER策略,非核心功能使用Observable -
動態緩存控制
通過rx2.buffer-size
參數調整Flowable緩存池:System.setProperty("rx2.buffer-size", "256"); // 默認128[7](@ref)
-
生命周期管理
使用CompositeDisposable
統一釋放資源:CompositeDisposable disposables = new CompositeDisposable();disposables.add(api.getDataStream().subscribe(data -> {...}));
通過合理選擇Flowable與Observable,可使Retrofit網絡層在保證穩定性的同時獲得最佳性能。可以在金融交易、物聯網等高頻場景優先采用Flowable,而在常規業務API中使用Observable以降低復雜度。