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

如何使用Retrofit2从API读取连续流式数据?

使用Retrofit2的@GET注解读取非JSON持续流数据

要处理这种持续传输的海量非JSON流数据,核心思路是绕开Retrofit的默认转换器,直接获取原始响应体的输入流来逐块读取数据,具体步骤如下:

1. 定义返回ResponseBody的API接口

在Retrofit接口中,让@GET方法返回ResponseBody而非自定义实体类,这样可以拿到原始的响应流:

public interface StreamingApi {
    @GET("/stream")
    Call<ResponseBody> getStreamingData();
}

如果用Kotlin协程,定义成挂起函数:

interface StreamingApi {
    @GET("/stream")
    suspend fun getStreamingData(): ResponseBody
}

2. 执行请求并持续读取流数据

调用接口后,通过ResponseBody获取输入流,循环读取数据直到流结束。注意要在后台线程处理,避免阻塞主线程:

Java示例(Callback方式)

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://example")
        .build();

StreamingApi api = retrofit.create(StreamingApi.class);
Call<ResponseBody> call = api.getStreamingData();

call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        if (!response.isSuccessful() || response.body() == null) {
            // 处理请求失败或空响应
            return;
        }

        try (InputStream inputStream = response.body().byteStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            
            String line;
            // 持续读取每一行数据(根据流格式调整读取逻辑)
            while ((line = reader.readLine()) != null) {
                processStreamingData(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        t.printStackTrace();
    }
});

// 自定义数据处理方法
private void processStreamingData(String rawData) {
    // 根据流的实际格式解析数据,比如分割字段、提取有效内容等
    System.out.println("Received chunk: " + rawData);
}

Kotlin协程示例

val retrofit = Retrofit.Builder()
    .baseUrl("https://example")
    .build()

val api = retrofit.create(StreamingApi::class.java)

CoroutineScope(Dispatchers.IO).launch {
    try {
        val responseBody = api.getStreamingData()
        responseBody.byteStream().use { inputStream ->
            BufferedReader(InputStreamReader(inputStream)).useLines { lines ->
                lines.forEach { line ->
                    processStreamingData(line)
                }
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

// 自定义数据处理函数
private fun processStreamingData(rawData: String) {
    println("Received chunk: $rawData")
}

3. 关键注意事项

  • 禁用JSON转换器:不要添加GsonConverterFactory等默认转换器,否则Retrofit会尝试一次性解析整个响应,导致解析失败或内存溢出。
  • 资源管理:务必用try-with-resources(Java)或use函数(Kotlin)自动关闭输入流,避免资源泄漏。
  • 线程处理:流读取操作耗时较长,必须放在后台线程执行,Android环境下可以用Coroutine的Dispatchers.IO或RxJava的io()调度器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 02:26:19