Android开发中Retrofit使用方法与底层原理详解

Retrofit 是 Android 开发中一个 类型安全、基于注解、高度解耦RESTful HTTP 客户端库,由 Square 公司开发。它极大地简化了 Android 应用与 Web 服务进行网络交互的过程。

核心价值:

  1. 声明式 API 定义: 使用 Java/Kotlin 接口和注解描述 API 端点,将 HTTP 请求细节(方法、路径、参数、头、体)从业务逻辑中分离。
  2. 类型安全: 利用泛型和 Converter 机制,自动将 HTTP 响应体(如 JSON/XML)反序列化为强类型的对象(POJO/Kotlin Data Class),将请求体序列化。
  3. 高度可扩展: 通过 Converter.Factory 支持多种数据格式(Gson, Moshi, Jackson, Protobuf 等),通过 CallAdapter.Factory 支持多种异步执行机制(Call, RxJava Observable/Single, Kotlin Coroutines suspend, CompletableFuture 等)。
  4. 与 OkHttp 深度集成: Retrofit 底层默认使用强大的 OkHttp 作为 HTTP 客户端,继承其所有优点(连接池、GZIP 压缩、缓存、拦截器等)。

一、使用流程 (Step-by-Step)

  1. 添加依赖:
    build.gradle (Module) 中添加必要的库:

    dependencies {// Retrofit 核心库implementation 'com.squareup.retrofit2:retrofit:2.9.0' // 使用最新稳定版// 选择数据转换器 (例如 Gson)implementation 'com.squareup.retrofit2:converter-gson:2.9.0'// 选择异步适配器 (例如 Kotlin Coroutines, RxJava3)implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0' // 或 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' (旧版适配器方式)// 或者直接使用 Retrofit 内置的协程支持(推荐,无需额外适配器)// Retrofit >=2.6.0 对 Kotlin 协程有原生支持 (suspend 函数)// OkHttp (通常需要)implementation 'com.squareup.okhttp3:okhttp:4.12.0'implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0' // 可选,用于日志
    }
    
  2. 定义数据模型 (POJO/Data Class):
    创建表示 API 请求和响应数据的 Java/Kotlin 类。这些类字段应与 JSON/XML 的键名匹配,或使用注解(如 Gson 的 @SerializedName)指定映射关系。

    data class User(val id: Long, val name: String, val email: String)
    data class LoginRequest(val username: String, val password: String)
    data class ApiResponse<T>(val code: Int, val message: String, val data: T)
    
  3. 定义 API 接口:
    创建一个 Java/Kotlin 接口,使用 Retrofit 注解描述 API 端点。

    interface ApiService {// GET 请求示例:获取用户列表@GET("users")fun getUsers(): Call<List<User>>// GET 请求带路径参数:根据 ID 获取用户@GET("users/{id}")fun getUserById(@Path("id") userId: Long): Call<User>// GET 请求带查询参数:搜索用户@GET("users/search")fun searchUsers(@Query("q") query: String): Call<List<User>>// POST 请求:登录 (发送请求体 LoginRequest, 接收 ApiResponse<String>)@POST("auth/login")fun login(@Body loginRequest: LoginRequest): Call<ApiResponse<String>>// 使用 Kotlin 协程 (suspend 函数)@GET("users/{id}")suspend fun getUserByIdCoroutine(@Path("id") userId: Long): User// 使用 RxJava3@GET("users")fun getUsersRx(): Observable<List<User>>
    }
    

    关键注解:

    • @GET, @POST, @PUT, @DELETE, @PATCH, @HEAD, @OPTIONS, @HTTP: 定义 HTTP 请求方法。
    • @Path: 替换 URL 路径中的占位符 ({id})。
    • @Query, @QueryMap: 添加 URL 查询参数。
    • @Body: 将参数对象作为请求体发送(会被配置的 Converter 序列化)。
    • @Field, @FieldMap: 用于 application/x-www-form-urlencoded 表单提交。
    • @Part, @PartMap: 用于 multipart/form-data 文件上传。
    • @Header, @Headers: 添加静态或动态的 HTTP 请求头。
    • @Url: 允许直接传递完整的 URL(覆盖 baseUrl)。
  4. 创建 Retrofit 实例:
    使用 Retrofit.Builder() 构建一个配置好的 Retrofit 对象。这是单例的最佳实践。

    object RetrofitClient {private const val BASE_URL = "https://api.example.com/"val instance: ApiService by lazy {// 创建 OkHttpClient (可配置拦截器、超时等)val okHttpClient = OkHttpClient.Builder().addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) // 添加日志拦截器.connectTimeout(30, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).build()// 构建 Retrofit 实例Retrofit.Builder().baseUrl(BASE_URL) // 基础 URL.client(okHttpClient) // 设置 OkHttpClient.addConverterFactory(GsonConverterFactory.create()) // 添加 Gson 转换器//.addConverterFactory(MoshiConverterFactory.create()) // 或 Moshi// 根据需要添加 CallAdapter (协程 suspend 函数通常不需要额外适配器).addCallAdapterFactory(RxJava3CallAdapterFactory.create()) // 添加 RxJava3 适配器//.addCallAdapterFactory(CoroutineCallAdapterFactory()) // 旧版协程适配器 (Retrofit <2.6.0).build().create(ApiService::class.java) // 创建 API 接口的实现}
    }
    
  5. 发起网络请求:

    • 传统 Call 方式:
      val call = RetrofitClient.instance.getUsers()
      call.enqueue(object : Callback<List<User>> {override fun onResponse(call: Call<List<User>>, response: Response<List<User>>) {if (response.isSuccessful) {val users = response.body() // 获取反序列化后的对象// 更新 UI (需切回主线程)} else {// 处理 HTTP 错误 (如 404, 500)val errorBody = response.errorBody()?.string()}}override fun onFailure(call: Call<List<User>>, t: Throwable) {// 处理网络错误 (如 IO 异常, 连接超时)}
      })
      // call.cancel() // 可以取消请求
      
    • Kotlin 协程方式 (suspend):
      viewModelScope.launch(Dispatchers.IO) { // 在 ViewModel 或协程作用域中try {val user = RetrofitClient.instance.getUserByIdCoroutine(1) // 直接调用 suspend 函数withContext(Dispatchers.Main) {// 更新 UI (在主线程)}} catch (e: Exception) {// 处理异常 (包括网络错误和 HTTP 错误)e.printStackTrace()}
      }
      
    • RxJava 方式:
      RetrofitClient.instance.getUsersRx().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe({ users ->// 更新 UI (在主线程)}, { throwable ->// 处理错误})
      

二、应用场景

  1. 获取 RESTful API 数据: 最常见的场景,从服务器获取列表数据(用户、商品、新闻)、详情数据等。
  2. 提交表单数据: 用户登录/注册、提交评论、填写调查问卷等。
  3. 文件上传: 使用 @Multipart@Part 上传图片、视频、文档等。@Part 类型可以是 MultipartBody.PartRequestBody
  4. 文件下载: 通过 Retrofit 获取 ResponseBody 流,然后写入文件。
  5. 身份验证:
    • 基本认证: 通过 @Header("Authorization") 添加 Basic 头。
    • Token 认证 (Bearer): 使用 @Header("Authorization") 添加 Bearer token。Token 管理通常结合 OkHttp Interceptor 自动添加。
    • OAuth: 同样可以通过拦截器处理复杂的 OAuth 流程。
  6. 请求重试与缓存策略: 利用 OkHttp 的 Interceptor 实现自定义重试逻辑和缓存控制。
  7. API 聚合/组合: 结合 RxJava 的 flatMap/zip 或 Kotlin 协程的 async/await,并行或顺序调用多个 API 并组合结果。
  8. Mock 测试: 利用 Retrofit 的 MockWebServer 或通过自定义 CallAdapter/Converter 进行单元测试,模拟网络响应。

三、实现原理深度剖析

Retrofit 的设计非常精妙,其核心在于 动态代理、注解解析、责任链模式强大的可扩展性

  1. 动态代理 (Proxy):

    • 当你调用 retrofit.create(ApiService::class.java) 时,Retrofit 使用 Java 的 Proxy.newProxyInstance() 动态创建了一个 ApiService 接口的实现类对象
    • 这个动态生成的代理对象,拦截了你对接口中定义的任何方法的调用。
    • 当调用代理对象的某个方法(如 getUserById(1))时,代理逻辑会捕获这次调用,获取方法对象 (Method)、方法参数 (args[]) 和注解信息。
  2. 注解解析与 ServiceMethod 构建:

    • 代理逻辑的核心是 ServiceMethod(或其子类 HttpServiceMethod)。
    • 对于每个接口方法,Retrofit 在第一次调用时(或通过缓存)会解析该方法上的所有注解(@GET, @Path, @Query 等)和方法参数。
    • 解析过程 (RequestFactory 或类似机制):
      • 确定 HTTP 方法(GET/POST 等)。
      • 解析相对 URL 和路径参数占位符。
      • 收集查询参数、表单字段、请求头、请求体等信息。
      • 确定参数如何绑定(路径替换、查询字符串、请求体等)。
    • 最终构建出一个 “请求模板” (RequestFactory)。这个模板知道如何根据具体的参数值构造出一个符合该 API 要求的 HTTP 请求。它本身还不是一个 okhttp3.Request 对象,但包含了构建它所需的所有规则和参数绑定信息。
  3. 请求构造 (okhttp3.Request):

    • 当实际调用发生时(例如 getUserById(1)),代理逻辑会:
      • 获取之前为该方法构建好的 ServiceMethod(包含 RequestFactory)。
      • 将传入的实际参数值(如 1)应用到 RequestFactory 上。
      • RequestFactory 根据参数值替换路径 ({id} -> 1),添加查询参数,构造请求头,序列化请求体(通过配置的 Converter)。
      • 最终生成一个具体的 okhttp3.Request 对象。
  4. Call 的创建与适配 (CallAdapter):

    • ServiceMethod 使用配置的 CallAdapter.Factory 列表来查找合适的 CallAdapter
    • CallAdapter 负责将底层 OkHttp 的 Call 对象适配成接口方法声明的返回类型。例如:
      • 如果方法返回 Call,则直接返回一个包装了 okhttp3.Call 的 Retrofit Call 对象。
      • 如果方法返回 RxJava 的 ObservableRxJava3CallAdapter 会创建一个 Observable,它在被订阅时发起网络请求,并通过 onNext/onError 发射结果或错误。
      • 如果方法是 Kotlin suspend 函数(Retrofit >=2.6.0),内置的 SuspendCallAdapter 会处理它。它本质上创建一个 Call,但在协程内部使用 suspendCancellableCoroutine 挂起协程,在 enqueue 的回调中恢复协程并返回结果或抛出异常。
  5. 发起请求与响应处理:

    • 最终生成的 Call 对象(无论是原始的 Retrofit Call,还是被适配器包装过的 Call 行为)底层都委托给一个 okhttp3.Call 对象。
    • 调用 call.enqueue() (异步) 或 call.execute() (同步) 会触发 OkHttp 执行实际的网络请求。
    • OkHttp 处理 DNS 解析、建立连接、发送请求、接收响应、处理重定向/重试、缓存等。
    • 当响应返回时:
      • OkHttp 得到一个 okhttp3.Response
      • Retrofit 首先检查 HTTP 状态码(200-299 视为成功)。
      • 如果成功: 使用配置的 Converter(如 GsonConverterFactory)将 Response.body() 的原始字节流反序列化为接口方法声明的返回类型(如 User 对象)。这个反序列化后的对象通过回调(Callback.onResponse)或作为 suspend 函数的返回值,或通过 RxJava 的 onNext 传递给上层。
      • 如果不成功: 尝试使用 Converter 解析 Response.errorBody()(如果 API 有错误体的约定),或者直接传递错误状态码和错误体字符串。错误通过 Callback.onFailure (对于网络错误或调用取消),或在 onResponse 中通过非成功状态码体现,或作为 suspend 函数抛出的异常,或通过 RxJava 的 onError 传递。
  6. 责任链模式 (OkHttp Interceptors):

    • Retrofit 本身不直接处理网络 IO,它完全依赖 OkHttp。
    • OkHttp 的核心是其强大的 拦截器 (Interceptor) 链。你可以添加自定义拦截器或使用内置拦截器(如日志拦截器 HttpLoggingInterceptor、重试拦截器、认证拦截器、缓存拦截器等)。
    • 请求 (Request) 会依次经过所有拦截器链(Application Interceptors -> RetryAndFollowUpInterceptor -> BridgeInterceptor -> CacheInterceptor -> ConnectInterceptor -> Network Interceptors -> CallServerInterceptor),每个拦截器都可以修改请求或提前返回响应。
    • 响应 (Response) 会逆着拦截器链返回,每个拦截器都可以修改响应或处理错误。
  7. 可扩展性 (Converter.Factory, CallAdapter.Factory):

    • Converter.Factory: 负责在 Java/Kotlin 对象和 HTTP 表示(请求体字节流 / 响应体字节流)之间进行转换。工厂模式允许根据类型(如方法的返回类型 Call)和注解动态选择具体的 Converter(如 GsonResponseBodyConverter)。
    • CallAdapter.Factory: 负责将底层 Call 对象适配成不同的异步执行模型(Call, Observable, Single, CompletableFuture, suspend 函数等)。工厂模式允许根据方法的返回类型(如 Observable)动态选择具体的 CallAdapter(如 RxJava3CallAdapter)。

总结流程图简化:

[ 开发者调用 ApiService.getUserById(1) ]|v
[ 动态代理拦截调用 ]| (获取 Method, 参数 args)v
[ ServiceMethod (缓存/解析) ]| (解析注解和参数类型,构建 RequestFactory)v
[ 应用参数值到 RequestFactory -> 构造 okhttp3.Request ]|v
[ CallAdapter.adapt(okhttp3.Call) -> 适配为返回类型 (e.g., Call<User>, Observable<User>, suspend fun) ]|v
[ 开发者使用适配后的对象发起请求 (e.g., call.enqueue(), subscribe(), 调用 suspend fun) ]|v
[ 底层 okhttp3.Call 执行,经过 OkHttp Interceptor 链 ]|v
[ 收到 okhttp3.Response ]|v
[ Retrofit 检查状态码 ]|--> [ 成功: Converter 反序列化 body -> 通过适配器传递结果 ]|--> [ 失败: 处理 errorBody 或错误 -> 通过适配器传递错误 ]

四、关键设计哲学与注意事项

  1. 约定优于配置: 通过接口和注解清晰定义 API 契约。
  2. 分层设计: Retrofit 专注于 API 定义、请求构建、响应转换和适配,将底层网络传输委托给 OkHttp,将数据转换委托给 Converter,将异步模型委托给 CallAdapter。
  3. 不可变性: Retrofit 实例、ServiceMethodCall(一旦创建)通常是不可变的,利于并发和安全。
  4. 性能: ServiceMethod 的解析和构建通常会被缓存,避免每次调用都进行反射和解析注解的开销。
  5. 错误处理: 必须妥善处理网络错误(onFailure/异常)和 HTTP 业务错误(非 2xx 状态码,response.isSuccessful)。不要忽略 errorBody()
  6. 线程切换: Retrofit 默认在后台线程执行网络请求。务必在主线程更新 UI。协程作用域(viewModelScope/lifecycleScope)和 RxJava 的 observeOn(AndroidSchedulers.mainThread())Callback 中的手动切换 (runOnUiThread/Handler/LiveData.postValue) 是常见做法。
  7. 生命周期管理: 取消不再需要的网络请求(尤其是在 Activity/Fragment 销毁时),避免内存泄漏和无效回调。ViewModelviewModelScopeRxJavaDisposable 可以很好地管理。
  8. Converter 选择: 根据 API 数据格式(JSON/XML/Protobuf)和性能需求选择合适的转换器(Gson, Moshi, Jackson, protobuf-converter)。Moshi 通常比 Gson 更快更轻量。
  9. 动态 URL/Header: 使用 @Url 参数或 Interceptor 处理动态变化的 Base URL 或需要动态添加的 Header(如 Token)。
  10. 测试: 利用 MockWebServer 模拟网络响应进行单元测试。也可以 Mock ApiService 接口进行更上层的测试。

结论:
Retrofit 通过其优雅的设计、强大的注解系统、灵活的扩展机制(Converter/CallAdapter)以及与 OkHttp 的无缝集成,成为了 Android 网络请求的事实标准。理解其使用流程、适用场景,特别是深入掌握其基于动态代理、注解解析和责任链模式的实现原理,对于高效、健壮地进行 Android 网络编程至关重要。它显著提升了开发效率,降低了网络层的复杂性,并保证了类型安全和代码的可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/web/89315.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于FPGA的IIC控制EEPROM读写(2)

基于FPGA的IIC控制EEPROM读写 文章目录基于FPGA的IIC控制EEPROM读写一、EEPROM简介二、代码实现——个人理解1、状态机2、仿真效果3、上板验证4、代码top.viic_master.vuart三、代码实现——复用性较高的IIC模块1、框架设计2、状态机设计3、仿真效果4、上板验证5、代码top.viic…

C# 界面程序在23H2型号系统中无法退出

20250716记录 环境&#xff1a;c# winform问题描述&#xff1a;主界面退出直接使用了Environment.Exit(0); 程序假死&#xff0c;无法关闭解决措施&#xff1a;//使用 this.Close();以下代码目标&#xff1a;执行完程序自身后&#xff0c;删除指定文件&#xff08;可用于程序文…

Kafka——集群核心参数配置

引言在分布式系统中&#xff0c;Kafka 凭借其高吞吐量、低延迟和强大的扩展性&#xff0c;成为数据管道和流处理的首选解决方案。然而&#xff0c;要充分发挥 Kafka 的性能和稳定性&#xff0c;正确配置集群参数至关重要。为什么参数配置如此重要&#xff1f;Kafka 的参数配置直…

单臂路由实现VLAN互通实验

实验拓扑图实验需求&#xff1a;按照图示为 PC3 和 PC4 配置 IP 地址和网关PC3 属于 Vlan10&#xff0c;PC4 属于 Vlan20&#xff0c;配置单臂路由实现 Vlan10 和 Vlan20 三层互通PC3 和 PC4 可以互通实验步骤&#xff1a;1.PC 配置 IP 地址2.PC3 属于 Vlan10&#xff0c;PC4 属…

基于渐进式迁移学习网络(PTLN)​的小样本故障诊断模型

目录 一、研究背景与挑战​ ​二、创新方法:渐进式迁移学习网络(PTLN)​​ ​1. 核心架构​编辑 ​2. 训练优化​ 三、核心代码 四、实验结果与优势​ ​1. 数据集​ ​2. 性能对比​ ​3. 关键验证​ 五、工程价值与未来方向​ 六、补充信息​ 一、研究背景与挑…

网络原理 —— HTTP

通过网络初识&#xff0c;我们认识了网络的协议栈&#xff0c;TCP/IP 分为五层&#xff1a;应用层&#xff0c;传输层&#xff0c;网络层&#xff0c;数据链路层&#xff0c;物理层。也介绍了其中的关键协议。而这些协议的理解&#xff0c;是我们写网络代码的基础。 应用层&…

docker--安装--原理

安装 链接 启动之后&#xff0c;docker状态查看&#xff1a; sudo systemctl status docker 添加普通用户到docker用户组&#xff1a; sudo usermod -aG docker $USER# 重启或者使用以下命令刷新组权限&#xff1a;newgrp docker 原理

Java并发第一篇(从零开始:一文读懂Java并发编程核心基础)

从零开始&#xff1a;一文读懂Java并发编程核心基础一. 为什么需要并发编程&#xff1f;二. 并发编程的“另一面”&#xff1a;挑战与代价2.1 频繁的上下文切换2.2 线程安全问题&#xff08;如&#xff1a;死锁&#xff09;三. 夯实基础&#xff1a;必须掌握的核心概念与操作3.…

【删库跑路】一次删除pip的所有第三方库

进入命令行&#xff0c;先list看下库存pip list导出所有的第三方库至一文件列表pip freeze >requirements.txt按照列表卸载所有库pip uninstall -r requirements.txt -y再list看下&#xff0c;可见库存已清空

python 【技术面试题和HR面试题】➕列表操作、条件判断、循环、函数定义编程题

1.技术面试题 &#xff08;1&#xff09;解释Linux中的进程、线程和守护进程的概念&#xff0c;以及如何管理它们&#xff1f; 答&#xff1a; 进程 概念&#xff1a;程序运行的实例&#xff0c;有独立资源&#xff08;如内存&#xff09;&#xff0c;是系统调度的基本单位。 管…

Debian 12中利用dpkg命令安装MariaDB 11.8.2

MariaDB 11.8解决了2038问题&#xff0c;即在32位系统中将timestamp从2038-01-19 03:14:07 UTC扩展到2106-02-07 06:28:15 UTC&#xff0c;向后延长了68年。由于写此文时Debian 12的源中还没有MariaDB 11.8,采用源码编译又太费时&#xff0c;可用二进制码或dpkg安装 .下面简要记…

Go语言高并发聊天室(三):性能优化与压力测试

Go语言高并发聊天室&#xff08;三&#xff09;&#xff1a;性能优化与压力测试 &#x1f3af; 本篇目标 在前两篇文章中&#xff0c;我们完成了聊天室的基础功能。本篇将深入性能优化&#xff0c;实现真正的高并发&#xff1a; &#x1f50d; 性能瓶颈分析⚡ 关键优化技术&…

【leetcode】852. 山脉数组的封顶索引

文章目录题目题解1. 遍历2. 二分查找题目 852. 山脉数组的封顶索引 给定一个长度为 n 的整数 山脉 数组 arr &#xff0c;其中的值递增到一个 峰值元素 然后递减。 返回峰值元素的下标。 你必须设计并实现时间复杂度为 O(log(n)) 的解决方案。 示例 1&#xff1a; 输入&a…

Java期末考试准备

文章目录Java期末考试准备一、Java的输入.next()输入.nextLine()输入区别补充二、Java的输出三、类中常写方法toString()equals()其他四、容器/数组五、继承六、静态属性、方法.七、抽象类八、接口九、初始化模块十、泛型考完结束语Java学习历程注:这篇文章本来是写给同学的&am…

飞算JavaAI进阶:重塑Java开发范式的AI革命

引言&#xff1a;当代码生成进入"自动驾驶"时代 在2025年的Java开发领域&#xff0c;一场由AI驱动的革命正在重塑传统开发范式。当GitHub Copilot还在通过代码补全提升效率时&#xff0c;飞算JavaAI已实现从需求分析到完整工程代码生成的"端到端"闭环。这款…

如何在银河麒麟桌面系统中启用 sudo 密码的星号反馈

引文 我们在银河麒麟桌面操作系统上使用 sudo 命令时&#xff0c;都遇到过这样的困扰&#xff1a;输入密码时光标一动不动&#xff0c;屏幕上没有任何提示&#xff08;没有星号 *&#xff0c;也没有任何字符&#xff09;&#xff1f;就像在黑暗中摸索钥匙孔一样&#xff0c;心里…

二刷 黑马点评 秒杀优化

优化逻辑 把耗时较短的逻辑判断放入redsi中&#xff0c;比如库存是否足够以及是否一人一单&#xff0c;只要这样的逻辑完成&#xff0c;就代表一定能下单成功&#xff0c;我们就将结果返回给用户&#xff0c;然后我们再开一个线程慢慢执行队列中的信息 问题&#xff1a; 如何快…

HANA SQLScript中的变量类型汇总

在 SAP HANA SQLScript 中&#xff0c;可以使用多种变量类型&#xff0c;包括标量&#xff08;Scalar&#xff09;类型、表类型和结构化类型。以下是各种变量类型的详细说明和示例。1. 标量变量&#xff08;Scalar Variables&#xff09; 标量变量是用于存储单个值&#xff08;…

基于 Amazon Nova Sonic 和 MCP 构建语音交互 Agent

1、引言 随着人工智能技术的飞速发展&#xff0c;自然语言处理和语音交互技术正在深刻改变人机交互的方式。语音交互正从简单的“机械应答”向更自然的“类人对话”演进 。传统的语音系统通常采用模块化架构&#xff0c;将语音处理流程割裂为 ASR&#xff08;自动语音识别&…

项目的存量接口怎么低成本接入MCP?

项目的存量接口怎么低成本接入MCP&#xff1f; 老项目里的一些接口&#xff0c;如何低成本的接入MCP&#xff08;0成本不可能&#xff09;&#xff0c;变成MCP server 的tools&#xff1f; 先抛出这个问题&#xff1f;评论区的xdm如果有懂的&#xff0c;可以打在评论区&#xf…