在自己撸了一遍自定义Converter与CallAdapter之后,终于有了一点了解,即使是局限与使用阶段。(另外本次的Demo参考了Retrofit2 探索)
源码地址:https://github.com/374901588/Retrofit2Demo.git
(注意:用于演示的Demo就是简单的把请求的结果set到TextView上了,没有做其他处理了)
用于测试的数据格式如下:
Contributor.java
为自定义的对应于上述数据的实体类,其中只包含login、id、contributions
三个属性。
1、首先是自定义Converter,我在这里模仿实现了GsonConverter
的功能,即在Demo中将Call<ResponseBody>
转换为Call<List<Contributor>>
。主要代码如下:
private static class CustomConverter implements Converter<ResponseBody,List<Contributor>> {
public static final CustomConverter INSTANCE=new CustomConverter();
@Override
public List<Contributor> convert(ResponseBody value) throws IOException {
List<Contributor> list=new Gson().fromJson(value.string(),new TypeToken<List<Contributor>>(){}.getType());
return list;
}
}
public static class CustomConverterFactory extends Converter.Factory {
public static final CustomConverterFactory INSTANCE = new CustomConverterFactory();
public static CustomConverterFactory create() {
return INSTANCE;
}
// 我们只关心从ResponseBody 到 List<Contributor>> 的转换,所以其它方法可不覆盖
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
//不能直接用type==new TypeToken<List<Contributor>>(){}.getType()),将会得到false
//因为==是用于判断两个引用变量是否相等,但是这里的==右边是new的一个新的,所以肯定是“不==”的
Log.d("测试---》",""+(type==new TypeToken<List<Contributor>>(){}.getType()));
if (type.equals(new TypeToken<List<Contributor>>(){}.getType())) {
return CustomConverter.INSTANCE;
}
//其它类型我们不处理,返回null就行
return null;
}
}
2、接着是实现自定义的CallAdapter,这里是模仿实现RxJavaCallAdapter
的功能,即在Demo中将Call<List<Contributor>>
转换为Observable<List<Contributor>>
。主要代码如下:
public static class CustomCallAdapter implements CallAdapter<List<Contributor>,Observable<List<Contributor>>> {
private final Type responseType;
CustomCallAdapter(Type type) {
responseType=type;
}
@Override
public Type responseType() {
return responseType;
}
@Override
public Observable<List<Contributor>> adapt(Call<List<Contributor>> call) {
Log.d("测试-----5","responseType="+responseType);
try {
List<Contributor> contributorList=call.execute().body();
return Observable.just(contributorList);
} catch (IOException e) {
Log.e("异常",e.getMessage());
}
return null;
}
}
public static class CustomCallAdapterFactory extends CallAdapter.Factory {
public static final CustomCallAdapterFactory INSTANCE=new CustomCallAdapterFactory();
/**
* returnType为需要转换的目标类型(原始类型),比如在本例中,需要转换为Observable<List<Contributor>>,所以returnType就为其原始类型,即Observable.class对应的类型
*/
@Override
public CallAdapter<?,?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType=getRawType(returnType);//提取returnType的原始类类型,例如,表示List <?扩展Runnable>返回List.class
//因此在对比的时候我们只要rawType==Observable.class,而不是与new TypeToken<Observable<List<Contributor>>>(){}.getType()对比
if (rawType==Observable.class&&returnType instanceof ParameterizedType) {
Type callReturnType=getParameterUpperBound(0,(ParameterizedType)returnType);
return new CustomCallAdapter(callReturnType);
}
return null;
}
}
由于本人能力有限,不能模仿得像原本的那么厉害,且迫于时间紧张,无心去分析源码,所以这里只是简易的实现功能。且需要注意执行contributors3()
方法时需要在子线程中,因为在CustomCallAdapter
的adapt()
方法中有执行call.execute()
,这会用于网络请求,如果执行contributors3()
方法时需要不在子线程中就会出现android.os.NetworkOnMainThreadException
。