Retrofit:优雅的JAVA网络请求框架实战

Retrofit:优雅的JAVA网络请求框架实战

本文深入讲解Square公司开源的Retrofit框架,从架构设计到实战应用,帮助你快速掌握这个强大的网络请求工具。

1. 引言:为什么选择Retrofit

在JAVA开发中,网络请求是绝大多数应用的核心功能。传统的HttpURLConnectionApache HttpClient使用繁琐,代码冗余。Retrofit由Square公司开源,它将RESTful API转化为Java接口,极大地简化了网络请求的编写。

1.1 Retrofit的核心优势

  • 声明式API定义 - 使用注解定义接口,代码简洁清晰
  • 自动序列化 - 内置Gson、Jackson等转换器,自动处理JSON
  • OkHttp集成 - 底层基于OkHttp,性能强大且稳定
  • 灵活的CallAdapter - 支持RxJava、协程等异步框架
  • 易于测试 - 接口化设计,便于Mock和单元测试

1.2 与其他框架的对比

特性 Retrofit OkHttp
API设计 声明式接口 原始API
学习曲线
扩展性 优秀 优秀
异步支持 多种方式 回调

2. 核心架构解析

Retrofit采用分层架构设计,每一层职责清晰,协同工作完成网络请求。

2.1 架构层次

应用层(Application Layer)

  • 定义API接口
  • 调用网络请求方法
  • 处理响应结果

Retrofit核心层

  • 动态代理拦截方法调用
  • 注解解析(@GET、@POST等)
  • 请求参数组装
  • 响应数据转换

OkHttp网络层

  • HTTP连接管理
  • 请求/响应拦截器链
  • 缓存策略
  • 连接池复用

网络传输层

  • TCP/IP协议通信
  • TLS/SSL加密
  • DNS解析

2.2 核心组件

java 复制代码
// 1. ServiceMethod - 封装接口方法的所有信息
class ServiceMethod<T> {
    private final okhttp3.Call.Factory callFactory;
    private final CallAdapter<T, ?> callAdapter;
    private final Converter<ResponseBody, T> responseConverter;
    // ...解析注解、构建请求
}

// 2. CallAdapter - 适配不同的异步框架
interface CallAdapter<R, T> {
    Type responseType();
    T adapt(Call<R> call);
}

// 3. Converter - 数据转换器
interface Converter<F, T> {
    T convert(F value) throws IOException;
}

// 4. Interceptor - 请求/响应拦截器
interface Interceptor {
    Response intercept(Chain chain) throws IOException;
}

3. 快速上手:基础用法

3.1 添加依赖

首先在build.gradle中添加依赖:

arduino 复制代码
dependencies {
    // Retrofit核心库
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'

    // Gson转换器(用于JSON解析)
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

    // RxJava适配器(可选)
    implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'

    // OkHttp日志拦截器(调试用)
    implementation 'com.squareup.okhttp3:logging-interceptor:4.10.0'
}

3.2 定义数据模型

typescript 复制代码
// 用户实体类
public class User {
    private int id;
    private String name;
    private String email;
    private String avatar;

    // Getter和Setter方法
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    public String getAvatar() { return avatar; }
    public void setAvatar(String avatar) { this.avatar = avatar; }
}

// API响应包装类
public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;

    public boolean isSuccess() {
        return code == 200;
    }

    // Getter和Setter
    public int getCode() { return code; }
    public String getMessage() { return message; }
    public T getData() { return data; }
}

3.3 定义API接口

less 复制代码
public interface UserService {

    // GET请求 - 查询用户信息
    @GET("users/{id}")
    Call<ApiResponse<User>> getUser(@Path("id") int userId);

    // POST请求 - 创建用户
    @POST("users")
    Call<ApiResponse<User>> createUser(@Body User user);

    // 带查询参数的GET请求
    @GET("users")
    Call<ApiResponse<List<User>>> listUsers(
        @Query("page") int page,
        @Query("size") int pageSize
    );

    // 带Header的请求
    @Headers("Content-Type: application/json")
    @GET("users/profile")
    Call<ApiResponse<User>> getProfile(
        @Header("Authorization") String token
    );

    // 文件上传
    @Multipart
    @POST("upload/avatar")
    Call<ApiResponse<String>> uploadAvatar(
        @Part MultipartBody.Part file,
        @Part("userId") RequestBody userId
    );

    // 表单提交
    @FormUrlEncoded
    @POST("login")
    Call<ApiResponse<String>> login(
        @Field("username") String username,
        @Field("password") String password
    );
}

3.4 创建Retrofit实例

typescript 复制代码
public class RetrofitClient {
    private static final String BASE_URL = "https://api.example.com/";
    private static Retrofit retrofit;

    // 单例模式获取Retrofit实例
    public static Retrofit getInstance() {
        if (retrofit == null) {
            synchronized (RetrofitClient.class) {
                if (retrofit == null) {
                    retrofit = new Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        .client(getOkHttpClient())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
                }
            }
        }
        return retrofit;
    }

    // 配置OkHttpClient
    private static OkHttpClient getOkHttpClient() {
        return new OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            .build();
    }

    // 获取API服务
    public static <T> T createService(Class<T> serviceClass) {
        return getInstance().create(serviceClass);
    }
}

3.5 发起网络请求

java 复制代码
public class UserRepository {
    private final UserService userService;

    public UserRepository() {
        userService = RetrofitClient.createService(UserService.class);
    }

    // 同步请求(不推荐在主线程使用)
    public User getUserSync(int userId) {
        try {
            Response<ApiResponse<User>> response =
                userService.getUser(userId).execute();

            if (response.isSuccessful() && response.body() != null) {
                ApiResponse<User> apiResponse = response.body();
                if (apiResponse.isSuccess()) {
                    return apiResponse.getData();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    // 异步请求(推荐)
    public void getUserAsync(int userId, final Callback<User> callback) {
        userService.getUser(userId).enqueue(new Callback<ApiResponse<User>>() {
            @Override
            public void onResponse(Call<ApiResponse<User>> call,
                                  Response<ApiResponse<User>> response) {
                if (response.isSuccessful() && response.body() != null) {
                    ApiResponse<User> apiResponse = response.body();
                    if (apiResponse.isSuccess()) {
                        callback.onSuccess(apiResponse.getData());
                        return;
                    }
                }
                callback.onError(new Exception("请求失败"));
            }

            @Override
            public void onFailure(Call<ApiResponse<User>> call, Throwable t) {
                callback.onError(t);
            }
        });
    }

    // 自定义回调接口
    public interface Callback<T> {
        void onSuccess(T data);
        void onError(Throwable error);
    }
}

4. 深入理解:请求执行流程

4.1 流程详解

当我们调用API接口方法时,Retrofit内部经历了以下7个步骤:

步骤1:调用API方法

ini 复制代码
Call<ApiResponse<User>> call = userService.getUser(100);

步骤2:动态代理拦截

Retrofit使用Java的动态代理机制,拦截接口方法调用:

typescript 复制代码
// Retrofit内部实现
public <T> T create(final Class<T> service) {
    return (T) Proxy.newProxyInstance(
        service.getClassLoader(),
        new Class<?>[] { service },
        new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) {
                // 拦截方法调用
                ServiceMethod<?> serviceMethod = loadServiceMethod(method);
                return serviceMethod.invoke(args);
            }
        }
    );
}

步骤3:解析方法注解

ini 复制代码
// 解析@GET、@POST、@Path、@Query等注解
ServiceMethod<?> serviceMethod = new ServiceMethod.Builder<>(retrofit, method)
    .build();

// 提取请求信息
String httpMethod = "GET";
String relativeUrl = "users/{id}";
Map<String, String> pathParams = new HashMap<>();
pathParams.put("id", "100");

步骤4:构建OkHttp请求

vbscript 复制代码
// 组装Request对象
Request request = new Request.Builder()
    .url("https://api.example.com/users/100")
    .method("GET", null)
    .build();

// 创建OkHttp Call
okhttp3.Call okHttpCall = okHttpClient.newCall(request);

步骤5:执行网络请求

less 复制代码
// 同步执行
Response response = okHttpCall.execute();

// 或异步执行
okHttpCall.enqueue(new okhttp3.Callback() {
    @Override
    public void onResponse(okhttp3.Call call, Response response) {
        // 处理响应
    }

    @Override
    public void onFailure(okhttp3.Call call, IOException e) {
        // 处理失败
    }
});

步骤6:响应数据转换

ini 复制代码
// 使用Converter将ResponseBody转换为Java对象
Converter<ResponseBody, ApiResponse<User>> converter =
    retrofit.responseBodyConverter(type, annotations);

ApiResponse<User> result = converter.convert(response.body());

步骤7:返回结果对象

swift 复制代码
// 通过CallAdapter包装返回结果
CallAdapter<ApiResponse<User>, Call<ApiResponse<User>>> callAdapter =
    retrofit.callAdapter(returnType, annotations);

return callAdapter.adapt(new OkHttpCall<>(serviceMethod, args));

4.2 源码分析:动态代理的妙用

kotlin 复制代码
// Retrofit核心方法
final class Retrofit {
    public <T> T create(final Class<T> service) {
        validateServiceInterface(service);

        return (T) Proxy.newProxyInstance(
            service.getClassLoader(),
            new Class<?>[] { service },
            new InvocationHandler() {
                private final Platform platform = Platform.get();
                private final Object[] emptyArgs = new Object[0];

                @Override
                public @Nullable Object invoke(Object proxy, Method method,
                    @Nullable Object[] args) throws Throwable {

                    // 如果是Object的方法,直接调用
                    if (method.getDeclaringClass() == Object.class) {
                        return method.invoke(this, args);
                    }

                    // 如果是默认方法(Java 8+),使用默认实现
                    if (platform.isDefaultMethod(method)) {
                        return platform.invokeDefaultMethod(method, service, proxy, args);
                    }

                    // 核心:加载并执行ServiceMethod
                    return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
                }
            }
        );
    }

    // 缓存ServiceMethod,避免重复解析
    ServiceMethod<?> loadServiceMethod(Method method) {
        ServiceMethod<?> result = serviceMethodCache.get(method);
        if (result != null) return result;

        synchronized (serviceMethodCache) {
            result = serviceMethodCache.get(method);
            if (result == null) {
                result = ServiceMethod.parseAnnotations(this, method);
                serviceMethodCache.put(method, result);
            }
        }
        return result;
    }
}

5. 高级特性:拦截器与转换器

5.1 拦截器链机制

拦截器(Interceptor)是OkHttp的核心机制,Retrofit继承了这一强大功能。拦截器分为两类:

应用拦截器(Application Interceptor)

  • 在请求发送前和响应返回后执行
  • 可以修改请求头、请求体
  • 可以记录日志、统计耗时

网络拦截器(Network Interceptor)

  • 在网络请求时执行
  • 可以访问连接信息
  • 可以处理重定向、缓存

5.1.1 自定义Token拦截器

java 复制代码
public class TokenInterceptor implements Interceptor {
    private String token;

    public TokenInterceptor(String token) {
        this.token = token;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();

        // 如果已有Authorization头,不做处理
        if (originalRequest.header("Authorization") != null) {
            return chain.proceed(originalRequest);
        }

        // 添加Token到请求头
        Request newRequest = originalRequest.newBuilder()
            .header("Authorization", "Bearer " + token)
            .build();

        return chain.proceed(newRequest);
    }
}

5.1.2 日志拦截器

ini 复制代码
public class LoggingInterceptor implements Interceptor {
    private static final String TAG = "OkHttp";

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        // 记录请求信息
        long startTime = System.nanoTime();
        Log.d(TAG, String.format("发送请求: %s %s",
            request.method(), request.url()));

        // 记录请求头
        Headers headers = request.headers();
        for (int i = 0; i < headers.size(); i++) {
            Log.d(TAG, headers.name(i) + ": " + headers.value(i));
        }

        // 执行请求
        Response response = chain.proceed(request);

        // 记录响应信息
        long endTime = System.nanoTime();
        double duration = (endTime - startTime) / 1e6d;

        Log.d(TAG, String.format("收到响应: %d %s (耗时%.1fms)",
            response.code(), response.request().url(), duration));

        return response;
    }
}

5.1.3 错误重试拦截器

java 复制代码
public class RetryInterceptor implements Interceptor {
    private int maxRetry = 3; // 最大重试次数
    private long retryDelay = 1000; // 重试延迟(毫秒)

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Response response = null;
        IOException exception = null;

        for (int i = 0; i <= maxRetry; i++) {
            try {
                response = chain.proceed(request);

                // 如果响应成功,直接返回
                if (response.isSuccessful()) {
                    return response;
                }

                // 关闭响应体
                if (response != null) {
                    response.close();
                }

            } catch (IOException e) {
                exception = e;
                Log.w("RetryInterceptor", "请求失败,尝试重试 " + (i + 1) + "/" + maxRetry);
            }

            // 如果不是最后一次重试,等待后再试
            if (i < maxRetry) {
                try {
                    Thread.sleep(retryDelay);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new IOException("重试被中断", e);
                }
            }
        }

        // 所有重试都失败,抛出异常
        if (exception != null) {
            throw exception;
        }

        return response;
    }
}

5.1.4 配置拦截器

scss 复制代码
OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(new TokenInterceptor("your_token_here"))
    .addInterceptor(new LoggingInterceptor())
    .addInterceptor(new RetryInterceptor())
    .connectTimeout(30, TimeUnit.SECONDS)
    .readTimeout(30, TimeUnit.SECONDS)
    .build();

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.example.com/")
    .client(client)
    .addConverterFactory(GsonConverterFactory.create())
    .build();

5.2 数据转换器(Converter)

Retrofit支持多种数据转换器,用于序列化和反序列化:

5.2.1 Gson转换器(最常用)

java 复制代码
// 添加依赖
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

// 自定义Gson配置
Gson gson = new GsonBuilder()
    .setDateFormat("yyyy-MM-dd HH:mm:ss")
    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
    .create();

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(BASE_URL)
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build();

5.2.2 Jackson转换器

ini 复制代码
// 添加依赖
implementation 'com.squareup.retrofit2:converter-jackson:2.9.0'

// 自定义ObjectMapper
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(BASE_URL)
    .addConverterFactory(JacksonConverterFactory.create(mapper))
    .build();

5.2.3 自定义转换器

scala 复制代码
public class CustomResponseConverter implements Converter<ResponseBody, ApiResponse<?>> {

    private final Gson gson;
    private final Type type;

    public CustomResponseConverter(Gson gson, Type type) {
        this.gson = gson;
        this.type = type;
    }

    @Override
    public ApiResponse<?> convert(ResponseBody value) throws IOException {
        String json = value.string();

        try {
            // 先解析为通用响应
            JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();

            // 检查响应码
            int code = jsonObject.get("code").getAsInt();
            String message = jsonObject.get("message").getAsString();

            // 如果失败,返回错误信息
            if (code != 200) {
                ApiResponse<?> errorResponse = new ApiResponse<>();
                errorResponse.setCode(code);
                errorResponse.setMessage(message);
                return errorResponse;
            }

            // 成功,解析data字段
            return gson.fromJson(json, type);

        } finally {
            value.close();
        }
    }
}

// 自定义Converter.Factory
public class CustomConverterFactory extends Converter.Factory {
    private final Gson gson;

    public CustomConverterFactory(Gson gson) {
        this.gson = gson;
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(
            Type type, Annotation[] annotations, Retrofit retrofit) {
        return new CustomResponseConverter(gson, type);
    }
}

5.3 CallAdapter(调用适配器)

CallAdapter用于适配不同的异步框架:

5.3.1 RxJava3适配器

less 复制代码
// 添加依赖
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'

// 配置Retrofit
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(BASE_URL)
    .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .build();

// 定义返回Observable的API
public interface UserService {
    @GET("users/{id}")
    Observable<ApiResponse<User>> getUser(@Path("id") int userId);

    @GET("users")
    Single<ApiResponse<List<User>>> listUsers();

    @POST("users")
    Completable createUser(@Body User user);
}

// 使用RxJava
userService.getUser(100)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
        response -> {
            // 成功处理
            if (response.isSuccess()) {
                User user = response.getData();
                // 更新UI
            }
        },
        error -> {
            // 错误处理
            Log.e("Error", "请求失败", error);
        }
    );

5.3.2 Kotlin协程适配器

kotlin 复制代码
// Kotlin代码示例
// 添加依赖
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'

// 定义suspend函数API
interface UserService {
    @GET("users/{id}")
    suspend fun getUser(@Path("id") userId: Int): ApiResponse<User>
}

// 在协程中调用
viewModelScope.launch {
    try {
        val response = userService.getUser(100)
        if (response.isSuccess) {
            val user = response.data
            // 更新UI
        }
    } catch (e: Exception) {
        // 错误处理
    }
}

6. 实战应用:生产级配置

6.1 完整的Retrofit配置

csharp 复制代码
public class NetworkModule {
    private static final String BASE_URL = "https://api.example.com/";
    private static final int TIMEOUT = 30; // 秒

    // 单例Retrofit实例
    private static volatile Retrofit retrofit;

    public static Retrofit provideRetrofit() {
        if (retrofit == null) {
            synchronized (NetworkModule.class) {
                if (retrofit == null) {
                    retrofit = new Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        .client(provideOkHttpClient())
                        .addConverterFactory(provideGsonConverterFactory())
                        .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                        .build();
                }
            }
        }
        return retrofit;
    }

    // 配置OkHttpClient
    private static OkHttpClient provideOkHttpClient() {
        return new OkHttpClient.Builder()
            // 超时配置
            .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
            .readTimeout(TIMEOUT, TimeUnit.SECONDS)
            .writeTimeout(TIMEOUT, TimeUnit.SECONDS)

            // 连接池配置
            .connectionPool(new ConnectionPool(5, 5, TimeUnit.MINUTES))

            // SSL证书信任(生产环境慎用)
            .hostnameVerifier((hostname, session) -> true)

            // 拦截器配置
            .addInterceptor(provideHeaderInterceptor())
            .addInterceptor(provideLoggingInterceptor())
            .addInterceptor(provideRetryInterceptor())

            // 缓存配置
            .cache(provideCache())

            .build();
    }

    // Header拦截器
    private static Interceptor provideHeaderInterceptor() {
        return chain -> {
            Request original = chain.request();
            Request request = original.newBuilder()
                .header("Content-Type", "application/json")
                .header("Accept", "application/json")
                .header("User-Agent", "Android App/1.0")
                .header("Authorization", "Bearer " + getToken())
                .method(original.method(), original.body())
                .build();
            return chain.proceed(request);
        };
    }

    // 日志拦截器
    private static Interceptor provideLoggingInterceptor() {
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(BuildConfig.DEBUG
            ? HttpLoggingInterceptor.Level.BODY
            : HttpLoggingInterceptor.Level.NONE);
        return logging;
    }

    // 重试拦截器
    private static Interceptor provideRetryInterceptor() {
        return new RetryInterceptor();
    }

    // 缓存配置
    private static Cache provideCache() {
        File cacheDir = new File(getApplication().getCacheDir(), "http_cache");
        int cacheSize = 10 * 1024 * 1024; // 10MB
        return new Cache(cacheDir, cacheSize);
    }

    // Gson配置
    private static GsonConverterFactory provideGsonConverterFactory() {
        Gson gson = new GsonBuilder()
            .setDateFormat("yyyy-MM-dd HH:mm:ss")
            .setLenient()
            .create();
        return GsonConverterFactory.create(gson);
    }

    // 获取Token(示例)
    private static String getToken() {
        // 从SharedPreferences或其他地方获取token
        return "your_token_here";
    }

    private static Application getApplication() {
        // 获取Application实例
        return MyApplication.getInstance();
    }
}

6.2 统一错误处理

java 复制代码
public class ApiException extends Exception {
    private int code;
    private String msg;

    public ApiException(int code, String msg) {
        super(msg);
        this.code = code;
        this.msg = msg;
    }

    // 错误码定义
    public static final int NETWORK_ERROR = -1;
    public static final int PARSE_ERROR = -2;
    public static final int UNKNOWN_ERROR = -3;
    public static final int AUTH_ERROR = 401;
    public static final int SERVER_ERROR = 500;

    // Getter
    public int getCode() { return code; }
    public String getMsg() { return msg; }
}

// 统一的响应处理器
public abstract class ApiCallback<T> implements Callback<ApiResponse<T>> {

    @Override
    public void onResponse(Call<ApiResponse<T>> call, Response<ApiResponse<T>> response) {
        if (response.isSuccessful()) {
            ApiResponse<T> body = response.body();
            if (body != null && body.isSuccess()) {
                onSuccess(body.getData());
            } else {
                onFailure(new ApiException(
                    body != null ? body.getCode() : ApiException.UNKNOWN_ERROR,
                    body != null ? body.getMessage() : "未知错误"
                ));
            }
        } else {
            onFailure(new ApiException(
                response.code(),
                "HTTP错误: " + response.code()
            ));
        }
    }

    @Override
    public void onFailure(Call<ApiResponse<T>> call, Throwable t) {
        if (t instanceof IOException) {
            onFailure(new ApiException(ApiException.NETWORK_ERROR, "网络连接失败"));
        } else if (t instanceof JsonSyntaxException) {
            onFailure(new ApiException(ApiException.PARSE_ERROR, "数据解析失败"));
        } else {
            onFailure(new ApiException(ApiException.UNKNOWN_ERROR, t.getMessage()));
        }
    }

    protected abstract void onSuccess(T data);
    protected abstract void onFailure(ApiException e);
}

// 使用示例
userService.getUser(100).enqueue(new ApiCallback<User>() {
    @Override
    protected void onSuccess(User user) {
        // 处理成功结果
        textView.setText(user.getName());
    }

    @Override
    protected void onFailure(ApiException e) {
        // 统一错误处理
        Toast.makeText(context, e.getMsg(), Toast.LENGTH_SHORT).show();
    }
});

6.3 多BaseUrl支持

在实际项目中,可能需要访问多个不同的API服务器:

less 复制代码
public class MultiBaseUrlInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        HttpUrl oldUrl = request.url();

        // 从请求头中获取自定义的BaseUrl标识
        String baseUrlName = request.header("BaseUrl");
        if (baseUrlName != null) {
            // 移除请求头
            request = request.newBuilder()
                .removeHeader("BaseUrl")
                .build();

            // 根据标识替换BaseUrl
            HttpUrl newBaseUrl = getBaseUrl(baseUrlName);
            if (newBaseUrl != null) {
                HttpUrl newUrl = oldUrl.newBuilder()
                    .scheme(newBaseUrl.scheme())
                    .host(newBaseUrl.host())
                    .port(newBaseUrl.port())
                    .build();

                request = request.newBuilder()
                    .url(newUrl)
                    .build();
            }
        }

        return chain.proceed(request);
    }

    private HttpUrl getBaseUrl(String name) {
        switch (name) {
            case "API_SERVER":
                return HttpUrl.parse("https://api.example.com/");
            case "IMAGE_SERVER":
                return HttpUrl.parse("https://img.example.com/");
            case "FILE_SERVER":
                return HttpUrl.parse("https://file.example.com/");
            default:
                return null;
        }
    }
}

// API接口定义
public interface FileService {
    @Headers("BaseUrl: FILE_SERVER")
    @Multipart
    @POST("upload")
    Call<ApiResponse<String>> uploadFile(@Part MultipartBody.Part file);
}

6.4 请求取消

typescript 复制代码
public class RequestManager {
    private final Map<String, Call<?>> callMap = new ConcurrentHashMap<>();

    // 添加请求
    public void addCall(String tag, Call<?> call) {
        callMap.put(tag, call);
    }

    // 取消指定请求
    public void cancelCall(String tag) {
        Call<?> call = callMap.remove(tag);
        if (call != null && !call.isCanceled()) {
            call.cancel();
        }
    }

    // 取消所有请求
    public void cancelAll() {
        for (Call<?> call : callMap.values()) {
            if (!call.isCanceled()) {
                call.cancel();
            }
        }
        callMap.clear();
    }
}

// Activity中使用
public class UserActivity extends AppCompatActivity {
    private RequestManager requestManager = new RequestManager();

    private void loadUser(int userId) {
        Call<ApiResponse<User>> call = userService.getUser(userId);
        requestManager.addCall("loadUser", call);

        call.enqueue(new ApiCallback<User>() {
            @Override
            protected void onSuccess(User user) {
                // 处理结果
            }

            @Override
            protected void onFailure(ApiException e) {
                // 处理错误
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Activity销毁时取消所有请求
        requestManager.cancelAll();
    }
}

7. 最佳实践

7.1 单例模式管理Retrofit

❌ 错误做法:

java 复制代码
// 每次都创建新实例,浪费资源
public User getUser(int id) {
    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.example.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

    UserService service = retrofit.create(UserService.class);
    // ...
}

✅ 正确做法:

csharp 复制代码
// 使用单例模式,全局共享
public class ApiClient {
    private static volatile ApiClient instance;
    private final Retrofit retrofit;

    private ApiClient() {
        retrofit = new Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .client(createOkHttpClient())
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    }

    public static ApiClient getInstance() {
        if (instance == null) {
            synchronized (ApiClient.class) {
                if (instance == null) {
                    instance = new ApiClient();
                }
            }
        }
        return instance;
    }

    public <T> T createService(Class<T> serviceClass) {
        return retrofit.create(serviceClass);
    }
}

7.2 合理配置超时时间

scss 复制代码
OkHttpClient client = new OkHttpClient.Builder()
    .connectTimeout(10, TimeUnit.SECONDS)    // 连接超时
    .readTimeout(30, TimeUnit.SECONDS)       // 读取超时
    .writeTimeout(30, TimeUnit.SECONDS)      // 写入超时
    .callTimeout(60, TimeUnit.SECONDS)       // 整个请求超时
    .build();

超时配置建议:

  • connectTimeout: 10-15秒(建立TCP连接的时间)
  • readTimeout: 30-60秒(等待服务器响应的时间)
  • writeTimeout: 30-60秒(向服务器写入数据的时间)
  • callTimeout: 60-120秒(整个请求流程的时间)

7.3 避免主线程阻塞

❌ 错误做法:

scss 复制代码
// 在主线程同步执行网络请求
User user = userService.getUser(100).execute().body();

✅ 正确做法:

less 复制代码
// 使用异步回调
userService.getUser(100).enqueue(new Callback<ApiResponse<User>>() {
    @Override
    public void onResponse(Call<ApiResponse<User>> call, Response<ApiResponse<User>> response) {
        // 处理响应(已在主线程)
    }

    @Override
    public void onFailure(Call<ApiResponse<User>> call, Throwable t) {
        // 处理失败
    }
});

// 或使用RxJava
userService.getUser(100)
    .subscribeOn(Schedulers.io())         // 在IO线程执行
    .observeOn(AndroidSchedulers.mainThread())  // 在主线程处理结果
    .subscribe(/* ... */);

7.4 合理使用缓存

java 复制代码
// 配置缓存策略
public class CacheInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        // 无网络时强制使用缓存
        if (!isNetworkAvailable()) {
            request = request.newBuilder()
                .cacheControl(CacheControl.FORCE_CACHE)
                .build();
        }

        Response response = chain.proceed(request);

        if (isNetworkAvailable()) {
            // 有网络时设置缓存有效期为1分钟
            int maxAge = 60;
            response = response.newBuilder()
                .removeHeader("Pragma")
                .removeHeader("Cache-Control")
                .header("Cache-Control", "public, max-age=" + maxAge)
                .build();
        } else {
            // 无网络时缓存保留4周
            int maxStale = 60 * 60 * 24 * 28;
            response = response.newBuilder()
                .removeHeader("Pragma")
                .removeHeader("Cache-Control")
                .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                .build();
        }

        return response;
    }

    private boolean isNetworkAvailable() {
        // 检查网络连接状态
        ConnectivityManager cm = (ConnectivityManager) context
            .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = cm.getActiveNetworkInfo();
        return networkInfo != null && networkInfo.isConnected();
    }
}

8. 总结

8.1 Retrofit核心要点

  1. 架构清晰 - 分层设计,职责明确
  2. 使用简单 - 声明式API,注解驱动
  3. 扩展性强 - 支持自定义Converter、CallAdapter、Interceptor
  4. 性能优秀 - 基于OkHttp,连接复用,缓存支持
  5. 生态丰富 - 与RxJava、Coroutine等框架无缝集成
相关推荐
Thexhy2 小时前
基础篇:Redis核心命令及用法
java·linux·redis
狂奔小菜鸡2 小时前
Day33 | Java中的Optional
java·后端·java ee
啃火龙果的兔子2 小时前
IntelliJ IDEA社区版下载安装
java·ide·intellij-idea
ckm紫韵2 小时前
Cursor 与 IDEA 互相跳转教程
java·ide·intellij-idea·cursor·ai工具
渡过晚枫2 小时前
[蓝桥杯/java/算法]攻击次数
java·算法·蓝桥杯
ByteX2 小时前
Java8-Function创建对象替代Builder
java·开发语言
飞火流星020272 小时前
【Arthas工具】使用Trace命令分析Java JVM方法调用链路及耗时
java·jvm·arthas·jvm性能调优·java方法调用链路分析及耗时·jvm实时分析·jvm方法调用实时分析
Han.miracle2 小时前
Spring MVC 请求参数处理全解析
java·请求
winfield8212 小时前
Java 的静态代理和动态代理
java·代理模式