之前写过一篇 浅谈Retrofit封装-让框架更加简洁易用 里面采用的是GsonConverterFactory,对于retrofit的返回类型要求只能是: 具体对象、jsonObject、jsonArray这三种。由于服务器返回的基础数据格式不固定,所以封装请求类的时候每个请求方式都要封装两个方法,而retrofit又必须添加一种解析器,本人对代码有洁癖,抽时间写了个StringConverterFactory将数据解析成最基本的String返回。
参考GsonConverterFactory源码,自定义解析器还是比较好写的,一共三个类,直接贴了
解析器 工厂
package com.sunshine.retrofit.converter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;
/**
* Created by 耿 on 2016/9/6.
*/
public class StringConverterFactory extends Converter.Factory {
public static StringConverterFactory create() {
return new StringConverterFactory();
}
private StringConverterFactory() {
}
@Override
public Converter responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return new StringResponseBodyConverter();
}
@Override
public Converter, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return new StringRequestBodyConverter();
}
}
Response响应体类
package com.sunshine.retrofit.converter;
import java.io.IOException;
import okhttp3.ResponseBody;
import retrofit2.Converter;
/**
* Created by 耿 on 2016/9/6.
*/
public class StringResponseBodyConverter implements Converter<ResponseBody, String> {
@Override
public String convert(ResponseBody value) throws IOException {
try {
return value.string();
} finally {
value.close();
}
}
}
Request 请求体类
package com.sunshine.retrofit.converter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import retrofit2.Converter;
/**
* Created by 耿 on 2016/9/6.
*/
public class StringRequestBodyConverter implements Converter<String, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
StringRequestBodyConverter() {
}
@Override public RequestBody convert(String value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
writer.write(value);
writer.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
在构建retrofit时替换掉原来的GsonConverterFactory就可以了
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL + "/")
.addConverterFactory(StringConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(OkhttpProvidede.okHttpClient(mAppliactionContext, BASE_URL, SERVERS))
.build();
这里要注意,retrofit对于解析器是由添加的顺序分别试用的,解析成功就直接返回,失败则调用下一个解析器。如果你们的服务器一开始基本返回格式不固定,而后来在你的建议或者坚持下,大发善心的把后面新需求的API的返回格式都固定了的话,可以按如下代码的方式将GsonConverterFactory添加在StringConverterFactory前面。这样如果是固定格式的就可以直接解析返回了。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL + "/")
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(StringConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(OkhttpProvidede.okHttpClient(mAppliactionContext, BASE_URL, SERVERS))
.build();
然后以后调用请求就可以直接
new HttpUtil.Builder("favorite_authorized/list?page=1")
.Version()
.CacheTime("3600*24")
.Params("carId", sb.toString())
.Params(sortMap_)
.Success((s) -> {
ld_.dismiss();
BaseModel model = new BaseModel(s);
})
.Error((v) -> {
ld_.dismiss();
handler_.obtainMessage(MSG, v[1]).sendToTarget();
})
.get();
});
再也不用去管返回格式是jsonObject还是jsonArray了。
我建了一个QQ群(群号:121606151),用于大家讨论交流Android技术问题,有兴趣的可以加下,大家一起进步。