我们目前正在为
XML API设置Retrofit – 不幸的是,每个请求都可以使用两个不同的根元素之一返回响应.
通常,每个响应都是这样的(当然,< response>标记中包含的实际元素随每个请求而变化):
Some Info
More Info
每个错误都是这样的(这里的结构对于每个响应都是相同的):
125002
现在,到目前为止我们发现的唯一方法是以一种通用的方式完成这项工作,如下所示:
public interface Api {
@GET("/api/sessionToken")
Observable requestSessionToken();
@GET("/api/pinStatus")
Observable requestPinStatus();
}
public class RestClient {
public RestClient() {
// ...
mApiService = retrofit.create(Api.class);
}
public Observable requestPinStatus() {
return mApiService.requestPinStatus()
.flatMap(foo(PinStatusResponse.class,PinStatusResponseData.class));
}
public Observable requestSessionToken() {
return mApiService.requestSessionToken()
.flatMap(foo(SessionTokenResponse.class,SessionTokenResponseData.class));
}
private final Func1> foo(final Class outerCls,final Class innerCls) {
return new Func1>() {
@Override
public Observable call(ResponseBody responseBody) {
try {
final String xmlString = responseBody.string();
final XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES,false);
parser.setInput(new ByteArrayInputStream(xmlString.getBytes(Charset.forName("UTF-8"))),null);
parser.nextTag();
final String rootTag = parser.getName();
final Serializer serializer = new Persister();
if (TextUtils.equals(rootTag,"error")) {
final MyError myError = serializer.read(MyError.class,xmlString);
return Observable.just((O) outerCls.getConstructor(MyError.class,innerCls).newInstance(myError,null));
} else if (TextUtils.equals(rootTag,"response")) {
final I data = serializer.read(innerCls,xmlString);
return Observable.just((T) outerCls.getConstructor(MyError.class,innerCls).newInstance(null,data));
}
} catch (XmlPullParserException e) {
return Observable.error(e);
} catch (IOException e) {
return Observable.error(e);
} catch (Exception e) {
return Observable.error(e);
}
return Observable.error(new Exception("Should not be reached..."));
}
};
}
}
Response类看起来像这样:
public abstract class MyResponse {
public final MyError error;
public final T data;
protected MyResponse(MyError error,T data) {
this.error = error;
this.data = data;
}
}
和:
public final class PinStatusResponse extends MyResponse {
public PinStatusResponse(MyError error,PinStatusResponseData data) {
super(error,data);
}
}
并且所有* Data类都直接对应于(非错误)XML响应.
现在,我的问题是:有没有更简单的方法来解决这个问题? (如果是这样,这是不良API设计的标志吗?).