目录
- 一、告别Callback地狱:声明式编程的魅力
- 1.1 传统网络请求的痛点
- 1.2 Retrofit的声明式革命
- 二、Retrofit核心配置工厂
- 2.1 构建Retrofit实例
- 2.2 常用注解速查表
- 三、RxJava响应式魔法
- 3.1 链式调用优雅变身
- 3.2 超能力操作符盘点
- 四、实战演练:构建天气查询客户端
- 4.1 定义天气接口
- 4.2 ViewModel中集成
- 4.3 动态更新UI
- 五、高级技巧:错误处理艺术
- 5.1 全局错误拦截器
- 5.2 响应统一包装
- 六、性能优化实战指南
- 6.1 请求缓存策略
- 6.2 合并重复请求
- 七、你该这样思考:架构师的视角
☕ 场景漫游:想象你在星巴克告诉咖啡师"一杯中杯拿铁,加燕麦奶,75度",后端服务调用API也该如此优雅!今天我们将用Retrofit+RxJava这对黄金组合,实现比咖啡订单更丝滑的API调用体验。
一、告别Callback地狱:声明式编程的魅力
1.1 传统网络请求的痛点
// 传统回调地狱案例
apiService.getUser(userId, new Callback<User>() {@Overridepublic void onResponse(Call<User> call, Response<User> response) {if (response.isSuccessful()) {apiService.getOrders(response.body().getId(), new Callback<List<Order>>() {@Overridepublic void onResponse(Call<List<Order>> call, Response<List<Order>> response) {// 处理订单数据...}// 省略错误处理...});}}// 省略错误处理...
});
灾难现场:
🌀 嵌套金字塔结构
🕳️ 错误处理分散
⏳ 线程切换复杂
1.2 Retrofit的声明式革命
public interface GitHubService {@GET("users/{user}/repos")Observable<List<Repo>> listRepos(@Path("user") String user);
}
魔法解析:
✅ 接口即文档
✅ 参数注解自动拼接URL
✅ 返回值类型自由定义(支持RxJava类型)
二、Retrofit核心配置工厂
2.1 构建Retrofit实例
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com/").addConverterFactory(GsonConverterFactory.create()) // JSON转换.addCallAdapterFactory(RxJava3CallAdapterFactory.create()) // RxJava支持.client(new OkHttpClient.Builder().addInterceptor(new HttpLoggingInterceptor()) // 请求日志.connectTimeout(10, TimeUnit.SECONDS).build()).build();
2.2 常用注解速查表
注解 | 作用示例 | 对应HTTP元素 |
---|---|---|
@GET | @GET(“users/{id}”) | GET请求 |
@Path | @Path(“id”) Long userId | URL路径参数 |
@Query | @Query(“sort”) String sort | URL查询参数 |
@Body | @Body LoginRequest request | 请求体 |
@Header | @Header(“Authorization”) | 请求头 |
三、RxJava响应式魔法
3.1 链式调用优雅变身
// 获取用户资料后获取最新动态
apiService.getUserProfile(userId).flatMap(user -> apiService.getLatestActivities(user.getId())).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(activities -> showActivities(activities),error -> showError(error));
操作符流程图:
(GetUser) → (FlatMap) → (GetActivities) → (UI展示)
3.2 超能力操作符盘点
// 并行请求用户信息和订单列表
Observable.zip(apiService.getUserInfo(userId),apiService.getUserOrders(userId),(userInfo, orders) -> new UserDashboard(userInfo, orders)
).subscribe(dashboard -> updateUI(dashboard));// 带超时和重试的请求
apiService.fetchData().timeout(5, TimeUnit.SECONDS).retryWhen(errors -> errors.flatMap(error -> {if (error instanceof SocketTimeoutException) {return Observable.timer(1, TimeUnit.SECONDS);}return Observable.error(error);})).subscribe(...);
四、实战演练:构建天气查询客户端
4.1 定义天气接口
public interface WeatherService {@GET("weather")Observable<WeatherData> getWeatherByCity(@Query("q") String city,@Query("appid") String apiKey);
}
4.2 ViewModel中集成
public class WeatherViewModel extends ViewModel {private final CompositeDisposable disposables = new CompositeDisposable();public void loadWeather(String city) {disposables.add(weatherService.getWeatherByCity(city, API_KEY).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).doOnSubscribe(d -> loadingState.setValue(true)).doFinally(() -> loadingState.setValue(false)).subscribe(data -> weatherData.postValue(data),error -> showError(error)));}@Overrideprotected void onCleared() {disposables.clear();}
}
4.3 动态更新UI
<androidx.swiperefreshlayout.widget.SwipeRefreshLayoutonRefresh="刷新天气数据"><TextViewandroid:id="@+id/tvTemperature"android:text="@{viewModel.weatherData.temp}℃" /><ImageViewandroid:src="@{viewModel.weatherData.getWeatherIcon()}" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
五、高级技巧:错误处理艺术
5.1 全局错误拦截器
public class GlobalErrorInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Response response = chain.proceed(chain.request());if (!response.isSuccessful()) {throw new HttpException(response.code(), response.message());}return response;}
}// 注入OkHttpClient
new OkHttpClient.Builder().addInterceptor(new GlobalErrorInterceptor())
5.2 响应统一包装
public class ApiResponse<T> {private T data;private Throwable error;public Observable<ApiResponse<T>> wrap(Observable<T> origin) {return origin.map(data -> new ApiResponse<>(data)).onErrorReturn(error -> new ApiResponse<>(error));}
}// 使用示例
apiService.fetchData().compose(new ApiResponseWrapper()).subscribe(response -> {if (response.hasError()) {// 处理错误} else {// 处理数据}});
六、性能优化实战指南
6.1 请求缓存策略
// 缓存控制拦截器
public class CacheInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();if (NetworkUtils.isNetworkAvailable()) {request = request.newBuilder().header("Cache-Control", "public, max-age=60").build();} else {request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=604800").build();}return chain.proceed(request);}
}
6.2 合并重复请求
// 使用RxJava的cache()操作符
Observable<List<Product>> productsObservable = apiService.getProducts().cache().subscribeOn(Schedulers.io());// 多个订阅者共享结果
productsObservable.subscribe(products -> updateList(products));
productsObservable.subscribe(products -> updateChart(products));
七、你该这样思考:架构师的视角
当你熟练使用Retrofit+RxJava后,可以尝试:
- 封装统一网络层模块
- 实现自动Token刷新机制
- 与Kotlin协程结合使用
- 编写API Mock测试模块
- 实施流量监控与报警
站在咖啡店的落地窗前,看着自己构建的声明式API客户端——它就像一杯精心调制的咖啡,每个操作符都是独特的调味剂,而Retrofit则是那个精准控制水温的咖啡机。现在,是时候用这些工具构建出属于你自己的美味代码了! ☕🚀