You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中Retrofit多API接口通用异步调用最优实现方案问询

这种重复编写异步调用逻辑的问题确实很烦人,我之前做Android项目的时候也遇到过,用泛型封装通用请求处理器就能完美解决,不管后续加多少接口,都不用再写重复的enqueue代码了。

解决方案:泛型封装通用异步请求处理

我们可以通过泛型来抽离通用的请求执行逻辑,让所有API接口都能复用同一套异步处理代码,核心思路是把Call的回调逻辑封装成通用方法,适配任意返回类型。

步骤1:定义通用的回调接口

先替换掉原来针对特定数据的ContributorsListener,改成泛型回调,适配所有返回类型:

public interface ApiCallback<T> {
    // 请求成功时回调,返回解析后的实体类/集合
    void onSuccess(T data);
    // 请求失败时回调,返回错误信息
    void onFailure(String errorMessage);
}

步骤2:封装通用的Retrofit客户端

把原来分散在GetSensorData里的Retrofit初始化、拦截器配置都移到一个单例客户端类里,同时提供两个核心方法:

  • createService:获取任意API接口的实例
  • executeCall:执行任意Call请求,并通过通用回调返回结果
public class ApiClient {
    // 全局单例Retrofit实例
    private static final Retrofit retrofit;

    static {
        // 配置Gson转换器
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();

        // 配置OkHttpClient,添加统一请求头
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(chain -> {
                    Request original = chain.request();
                    Request request = original.newBuilder()
                            .addHeader("Accept", "application/json")
                            .addHeader("Authorization", "Bearer " + Common.TOKEN_ACCESS)
                            .method(original.method(), original.body())
                            .build();
                    return chain.proceed(request);
                })
                // 可选:添加日志拦截器,方便调试
                // .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                .build();

        // 初始化Retrofit
        retrofit = new Retrofit.Builder()
                .baseUrl(API_BASE_URL) // 替换成你的实际BaseURL
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }

    /**
     * 获取任意API接口的实例
     * @param serviceClass API接口的Class对象
     * @return 接口实例
     */
    public static <T> T createService(Class<T> serviceClass) {
        return retrofit.create(serviceClass);
    }

    /**
     * 通用异步请求执行方法
     * @param call Retrofit生成的Call对象
     * @param callback 通用回调
     * @param <T> 返回数据类型
     */
    public static <T> void executeCall(Call<T> call, ApiCallback<T> callback) {
        call.enqueue(new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, Response<T> response) {
                if (response.isSuccessful()) {
                    // 请求成功,返回解析后的实体
                    callback.onSuccess(response.body());
                } else {
                    // 处理非2xx状态码的错误
                    String errorMsg = response.message().isEmpty() 
                            ? "请求失败,状态码:" + response.code() 
                            : response.message();
                    callback.onFailure(errorMsg);
                }
            }

            @Override
            public void onFailure(Call<T> call, Throwable t) {
                // 处理网络错误
                String errorMsg = t.getMessage() != null ? t.getMessage() : "未知网络错误";
                callback.onFailure(errorMsg);
            }
        });
    }
}

步骤3:简化原API接口

把原来GetSensorData里的Retrofit相关配置移除,只保留接口方法即可:

public interface GetSensorData {
    @GET("data/normal/{station}/{type}/{period}/{duration}")
    Call<SensorData> getSensorDetails(
            @Path("station") String station,
            @Path("type") String type,
            @Path("period") String period,
            @Path("duration") String duration
    );

    @GET("user/stations")
    Call<List<Station>> getStationList();

    // 后续新增接口直接在这里添加即可
}

步骤4:使用通用请求处理器

现在不管调用哪个接口,都可以用同一套代码,不用再重复写enqueue逻辑:

// 1. 获取API接口实例
GetSensorData sensorApi = ApiClient.createService(GetSensorData.class);

// 2. 调用传感器数据接口
Call<SensorData> sensorCall = sensorApi.getSensorDetails("00000146", "hourly", "last", "5");
ApiClient.executeCall(sensorCall, new ApiCallback<SensorData>() {
    @Override
    public void onSuccess(SensorData data) {
        // 处理成功返回的SensorData数据
        Log.d("SensorData", "获取成功:" + data.toString());
    }

    @Override
    public void onFailure(String errorMessage) {
        // 处理错误
        Log.e("SensorError", "请求失败:" + errorMessage);
    }
});

// 3. 调用站点列表接口(复用同一套逻辑)
Call<List<Station>> stationCall = sensorApi.getStationList();
ApiClient.executeCall(stationCall, new ApiCallback<List<Station>>() {
    @Override
    public void onSuccess(List<Station> data) {
        // 处理成功返回的站点列表
        Log.d("StationList", "获取成功:" + data.size() + "个站点");
    }

    @Override
    public void onFailure(String errorMessage) {
        // 处理错误
        Log.e("StationError", "请求失败:" + errorMessage);
    }
});

额外优化(可选)

如果你的项目支持Java 8+,可以用Lambda表达式简化回调代码,让它更简洁:

ApiClient.executeCall(sensorCall, new ApiCallback<>() {
    @Override
    public void onSuccess(SensorData data) {
        // 处理数据
    }

    @Override
    public void onFailure(String errorMessage) {
        // 处理错误
    }
});

如果想进一步简化,还可以结合LiveData或者RxJava来实现响应式的请求处理,但上面的方案已经完全解决了你的核心需求:一套代码处理所有接口的异步请求,后续新增接口只需要在API接口里定义方法,然后重复调用createService和executeCall即可,不用再写任何异步逻辑。

内容的提问来源于stack exchange,提问作者user2908751

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:47:20