GraphQL
重新定义了接口查询,不过现在使用上还是有许多问题,因为最近的项目中用到了,现将错误记录下来。
使用一:生成schema.json
文件
生成schema
文件需要使用 apollo-codegen
,使用它需要安装node
环境:
npm install -g apollo-codegen
如果未安装npm
, 那还需要安装npm
转换schema.json
文件:
apollo-codegen download-schema server-url --output schema.json
错误一 : Did you forget to add custom type adapter?
# 有一个新的 字段 DateTime
Representation of date and time in "Y-m-d H:i:s" format
scalar DateTime
后台定义了一个新的标量类型DateTime
, 当使用Apollo
自动生成对象类型时,会在package/type/
下生成一个CustomType
对象, 里面会自动生成你定义好的自定义标量,但是Apollo
还找不到你定义好的自定义标量,需要将其告诉Apollo Client
:
步骤:
1、 添加类型告诉Apollo
, 在使用apply plugin: 'com.apollographql.android'
的build.gradle
中最下面添加(层级与android{}
相同):
apollo {
customTypeMapping = [
"DateTime" : "java.util.Date",
]
}
2、注册类型到Apollo Client
中
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.ENGLISH);
CustomTypeAdapter<Date> dateCustomTypeAdapter = new CustomTypeAdapter<Date>() {
@Override
public Date decode(CustomTypeValue value) {
try {
return simpleDateFormat.parse(value.value.toString());
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
@Override
public CustomTypeValue encode(Date value) {
return new CustomTypeValue.GraphQLString(simpleDateFormat.format(value));
}
};
// 初始化ApolloClient
mApolloClient = ApolloClient.builder()
.serverUrl(getHost(hostType))
.okHttpClient(getOkHttpClient())
.addCustomTypeAdapter(CustomType.DATETIME, dateCustomTypeAdapter)
.build();
到这里,就可以将你的2019-04-16 00:00:00
转换成Date
类型。
错误二 : Apollo
对象名字一样
假设你的schema.json
文件中,后台定义好的对象有一个是这样的
// Prop 对象定义
{
"kind": "OBJECT",
"name": "Prop",
"description": null,
"fields": [
{
"name": "country",
"description": null,
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "CountryLabelValue",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
]
....
}
// CountryLabelValue 对象
{
"kind": "OBJECT",
"name": "CountryLabelValue",
"description": "Country Value Label",
"fields": [
{
"name": "value",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "ENUM",
"name": "Country",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
]
}
聪明的你会发现,CountryLabelValue
对象的名字是Country
, 而CountryLableValue
中又包含一个类型为ENUM
类型的Country
,导致Apollo
在自动生成对象的时候,找不到该对象, 在自动生成的对象中,你可以找到如下错误:
writer.writeList($responseFields[2], propertyCountries, new ResponseWriter.ListWriter() {
@Override
public void write(List items, ResponseWriter.ListItemWriter listItemWriter) {
for (Object item : items) {
listItemWriter.writeObject(((Country) item).rawValue());
}
}
});
这个地方的Country
其实应该List
类型的CountryLabelValue
, 但是同一个对象中包含的其他对象名字与它冲突了,搜索Apollo
中的issue
发现有人遇到了同样的问题:
https://github.com/apollographql/apollo-android/issues/1156
具体的解决方法是添加别名
:
prop{
gateway{
label
value
}
country {
label
value
}
payment_status{
label
value
}
}
修改为:
prop{
gateway{
label
value
}
propertyCountries : country {
label
value
}
payment_status{
label
value
}
}
这样就不会在编译的时候报错了,而最后生成的对象变成了这样:
writer.writeList($responseFields[2], propertyCountries, new ResponseWriter.ListWriter() {
@Override
public void write(List items, ResponseWriter.ListItemWriter listItemWriter) {
for (Object item : items) {
listItemWriter.writeObject(((PropertyCountry) item).marshaller());
}
}
});
字段变成了你设置的别名