Android AI解放生产力(五)实战:解放写API接口的繁琐工作

公司当前项目使用的是Apifox作为API调试/文档工具,所以以这个为例。市面上的工具应该都逐步开放了AI能力,需要关注一下,只要能提供原始数据就行,不能的话那也没办法喂给AI。

上一篇已经让AI写UI了,这一篇让AI写接口请求。首先思考一下可能碰到的问题。

一、可能遇到的问题

默认网络请求用的retrofit,其它也是一通百通。

1、问题一:适配请求头

项目中网络请求的拦截器已经定义了请求头,读取的原始数据如何关联?答案就是在skill中告诉AI,并让它模仿你的代码写。

2、问题二:适配请求参数中有一些公共部分

项目中网络请求的拦截器已经定义了一些公共请求参数,读取的原始数据如何关联?例如:

kotlin 复制代码
{
    "app": {
        "locale": "{{locale}}",
        "tid": "{{terminal_id}}",
        "platform": "{{platform}}"
    },
    "data": {
        //每个接口只有这里有差异
    }
}

只有data块中有差异。答案其实同上,skill中告诉AI,并让它模仿你的代码。

3、问题三:返回数据脱壳

例如项目中的壳是这样:

kotlin 复制代码
data class ApiResponse<T>(
    val code: Int,
    val msg: String,
    val data: T
) : BaseResponse<T>() {...}

那我们需要的解析的Data Class可能只需要脱壳的部分,如何让AI知道?答案也同上,skill中告诉AI,并让它模仿你的代码。

4、问题四:viewmodel中网络请求如何写

道理同上。

5、问题五:代码放在哪个文件

这个问题的解答要看情况了,我们先看下面只给代码的示例,最后再探讨一下这个问题。

二、获取接口原始数据

这一步依赖MCP的开放能力,后端兄弟接口怎么定义的,字段怎么写的,Android如何封装Data Class都依赖这些原始数据。接下来看通过Apifox如何办到的。

Apifox的MCP现阶段还不能集成到Codex中使用,启动的时候会报错:

kotlin 复制代码
⚠ MCP client for `apifox_api_docs` failed to start: MCP startup failed: handshaking with MCP server failed: connection closed: initialize response
⚠ MCP startup incomplete (failed: apifox_api_docs)

原因是Apifox的MCP返回不符合Codex定义的规范。

那换其他方式,打开Apifox终端(当前V版本2.7.58 (2.7.58)),选择需要生成代码的接口:

如上操作,可以得到复制的一段信息如下:

kotlin 复制代码
请访问以下链接获取接口"天气信息V3"的接口定义信息:https://api.apifox.cn/temp-links/api/%E5%A4%A9%E6%B0%6%81%AFv3-253061517?t=e0be3ab5-e8bf-4ec2-be81-f1489

这样我们就拿到了接口的原始数据链接。

三、如何编辑skills

这一步跟项目强关联,因为每个项目写法都不一样,文件不一样,所以skill的写法因项目而异,下面贴一份剔除敏感信息后的skill,抛砖引玉:

kotlin 复制代码
---
name: api_to_request
description: 请访问链接获取接口定义信息。
---
## 请访问链接获取接口定义信息,给出如下要求的代码:

### 1、代码一:生成retrofit接口定义
`java/api` 文件夹内是定义的retrofit api 请求的接口,例如其中的一例:

/**
 * 获取Camera Event事件
 */
@POST("/v1/iot/camera/discoverXXX")
suspend fun discoverXxx(@Body request: Request): ApiResponse<Response?>

请按照链接中的请求类型给出类似上面的接口定义。

### 2、代码二:给出请求的@Body
一般的请求数据示例是下面这样的:

{
    "data": {
        "dev_id": "xxx"
    },
    "app": {
        "locale": "en_AU",
        "tid": "8AE4EC1E36904B869D03FC9BABE4C087",
        "alias": "Kevin 的 A52",
        "platform": "foxx"
    }
}

为了避免每次都给出重复的参数,我在retrofit添加了一个拦截器,请参考`AddPublicParamsInterceptor.kt`文件,这里是添加公共请求参数的地方。所以@Body中只需要给出data节点的内容即可,如果data节点内的内容为空,那就不需要给出任何参数,因为`AddPublicParamsInterceptor.kt`中会默认添加`{}`.

### 3、代码三:给出返回的response
返回的数据使用`ApiResponse.kt`剥壳,所以给出的response数据应该是剥壳后的数据,一般是一个data class类。请参考`java/data`文件夹内其他response的写法给出。

### 4、代码四:viewmodel中实际请求的代码
viewmodel中实际请求的代码请参考下面的代码给出:

    /**
     * 获取设备同步授权码
     */
    fun syncAppDevice(
        buffer: MeshBanBindBuffer,
        success: (Any?) -> Unit,
        fail: (ApiHttpExceptionResponse<Any?>) -> Unit,
        error: (AppException) -> Unit
    ) {
        val request = SyncAppDeviceRequest(...)
        requestWithHttpException({ apiService.syncAppDevice(request) }, success = {
            success(it)
        }, fail = {
            fail(it)
        }, error = {
            error(it)
        })
    }

根据项目情况可以写的更丰富,更详细。

Apifox复制链接的内容因为匹配skill的description,所以给出链接就可以触发上面的skill。Codex生成的代码如下(剔除了敏感信息):

kotlin 复制代码
• 使用 api_to_request 技能,因为需要从接口文档生成 Retrofit 请求、请求体、响应体与 ViewModel 调用代码。(api.apifox.cn (https://api.apifox.cn/temp-links/api/
  %E5%A4%A9%E6%F%A1%E6%81%AFv3-253061517?t=e0be3ab5-e8bf-4ec2-be81-f148d9))

  代码一:Retrofit 接口定义(api.apifox.cn (https://api.apifox.cn/temp-links/api/%E5%A4%A9%E6%A1%E6%81%AFv3-253061517?t=e0be3ab5-e8bf-4ec2-be81-
  f14569))

  /**
   * 天气信息V3
   */
  @POST("/v1/iot/weather/getCurrentInfo")
  suspend fun getCurrentInfoV3(@Body request: WeatherInfoV3Request): ApiResponse<WeatherInfoV3Response?>

  代码二:@Body(仅 data 节点)(api.apifox.cn (https://api.apifox.cn/temp-links/api/%E5%A4%A9%E6%%E6%81%AFv3-253061517?t=e0be3ab5-e8bf-4ec2-be81-
  f8569))

  data class WeatherInfoV3Request(
      var lon: Double,
      var lat: Double,
      var unit: String = "IMPERIAL" // METRIC / IMPERIAL
  )

  代码三:Response(剥壳后的 data)(api.apifox.cn (https://api.apifox.cn/temp-links/api/%E5%A4%A9%E6%F%A1%E6%81%AFv3-253061517?t=e0be3ab5-e8bf-4ec2-
  be81-f18569))

  data class WeatherInfoV3Response(
      var day: Boolean?,
      var weather: WeatherV3?,
      var temperature: Double?,
      var wind: Double?,
      var pressure: Double?,
      var humidity: Double?,
      var aqi: String?
  )

  data class WeatherV3(
      var condition: String?,
      var icon: String?
  )

  代码四:ViewModel 中实际请求代码(api.apifox.cn (https://api.apifox.cn/temp-links/api/%E5%A4%A9%%A1%E6%81%AFv3-253061517?t=e0be3ab5-e8bf-4ec2-
  be81-f1469))

  /**
   * 获取天气信息V3
   */
  fun getCurrentInfoV3(
      lon: Double,
      lat: Double,
      unit: String = "IMPERIAL",
      success: (WeatherInfoV3Response?) -> Unit,
      fail: (ApiHttpExceptionResponse<Any?>) -> Unit,
      error: (AppException) -> Unit
  ) {
      val request = WeatherInfoV3Request(
          lon = lon,
          lat = lat,
          unit = unit
      )
      requestWithHttpException({ homeManagementApiService.getCurrentInfoV3(request) }, success = {
          success(it)
      }, fail = {
          fail(it)
      }, error = {
          error(it)
      })
  }

生成的代码可用度极高,很大程度上解放了生产力。

四、AI的放权

AI生成的代码可用度这么高,那是不是应该放权直接让AI写文件呢?

1、如果是一个新项目,定义好项目架构后就大胆的让AI生成文件自己写代码吧,能"摸鱼"就别动手,人生苦短我用AI。

2、如果是一个成熟度高的项目,建议以小颗粒度的形式让AI生成或修改文件代码,这样影响的范围可控,git提交的时候请仔细审查AI生成的代码。

3、如果是一个成熟度高的项目,修改的需求复杂,牵扯面广,或者公司规定不让AI写代码只让辅助参考,那还是开只读模式自己写吧。

回到最上面的问题五:代码放哪个文件?

答案就简单了。

  • 项目架构清晰,让AI干活,可以完全让AI自主决策,后续自己调整。
  • 可以在skill中添加提示加以引导,让AI放哪个文件/目录。
  • 只读模式,自己处理AI生成的代码,前期可以开只读熟悉AI的使用,等熟练后就可以让AI自己写文件了。
相关推荐
csj504 小时前
安卓基础之《(6)—Activity组件(3)》
android
怀旧,4 小时前
【Linux系统编程】13. Ext系列⽂件系统
android·linux·缓存
Dabei4 小时前
Android 语音助手简单实现与语音助手“执行任务”交流
android·前端
jzlhll1234 小时前
android NDSDManager onResolveFailed errorCode=3的解决方案
android
芦半山5 小时前
四年之后,重新审视 MTE:从硬件架构到工程落地
android·安全
2501_916007475 小时前
iOS与Android符号还原服务统一重构实践总结
android·ios·小程序·重构·uni-app·iphone·webview
allk555 小时前
Android 屏幕适配全维深度解析
android·性能优化·界面适配
Android系统攻城狮5 小时前
Android ALSA驱动进阶之获取采样格式位宽snd_pcm_format_width:用法实例(九十八)
android·pcm·音频进阶·alsa驱动
莫比乌斯环6 小时前
【日常随笔】Android 跳离行为分析 - Instrumentation
android·架构·代码规范