如何让同类型GraphQL查询返回OrderResult,解决类型不匹配问题?
解决Apollo GraphQL查询类型不匹配问题
核心原因
Apollo默认使用operationBased代码生成模式,每个查询会生成独立的Kotlin数据类——哪怕GraphQL返回的是同一底层类型,也会被拆分成不同的类(比如FindOrderByRestaurantIdQuery.FindOrderByRestaurantId和FindOrderByOidQuery.FindOrderByOid),直接导致类型不兼容。
解决方案
1. 修改Apollo代码生成模式
在Gradle的Apollo配置中,启用responseBased模式,让相同的GraphQL类型生成共用的Kotlin类:
apollo { service("myapp") { packageName.set("com.myapp.app") // 启用responseBased模式,共用GraphQL类型对应的Kotlin类 codegenModels.set("responseBased") introspection { endpointUrl.set("https://endpoint.com/data/") schemaFile.set(file("src/main/graphql/sg/com/myapp/app/schema.graphqls")) } customTypeMapping = [ "Date" : "kotlin.String", "DateTime": "kotlin.String", "Time" : "kotlin.String", "BigInt" : "kotlin.Long", "Double" : "kotlin.Double" ] } }
2. 使用GraphQL Fragment复用字段定义
创建Fragment文件(路径示例:src/main/graphql/com/myapp/app/OrderResultFragment.graphql),统一定义OrderResult类型的所有字段:
fragment OrderResultFragment on OrderResult { # 列出OrderResult的所有字段,比如: id oid restaurantId # ... 其他近百个字段,直接从Schema中复制即可 }
然后在两个查询文件中引用该Fragment,确保返回结果类型统一:
FindOrderByRestaurantIdQuery.graphql:
query FindOrderByRestaurantId($id: String!) { findOrderByRestaurantId(id: $id) { ...OrderResultFragment } }
FindOrderByOidQuery.graphql:
query FindOrderByOid($oid: String!) { findOrderByOid(oid: $oid) { ...OrderResultFragment } }
3. 更新Kotlin代码中的集合类型
将orderListData的类型改为Fragment对应的共用类型,调整后的代码如下:
// 统一使用OrderResultFragment类型 var orderListData: ArrayList<OrderResultFragment?> = ArrayList() fun getOrderList(){ scope.launch { apolloBuilder.apolloBuild().query( FindOrderByRestaurantIdQuery( id = "1" ) ).execute().apply { orderListData = data?.findOrderByRestaurantId?.toCollection(ArrayList()) ?: ArrayList() } } } fun getOrderDetail(){ scope.launch { apolloBuilder.apolloBuild().query( FindOrderByOidQuery( oid = "15" ) ).execute().apply { data?.findOrderByOid?.let { orderListData.add(it) } } } }
4. 清理并重新构建项目
- 删除旧的生成代码(默认路径:
build/generated/source/apollo) - 执行
./gradlew clean build重新生成代码并构建项目
注意事项
- 若需兼容旧代码,可改用
compatible代码生成模式(codegenModels.set("compatible")),它会同时生成共用类型和旧的操作专属类型 - 确保Fragment包含的字段与两个查询原本返回的字段完全一致,避免遗漏或冗余
内容的提问来源于stack exchange,提问作者newbie
相关产品推荐
相关产品推荐

