Retrofit2学习番外——自定义Converter与CallAdapter

    xiaoxiao2021-03-25  87

    在自己撸了一遍自定义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。

    转载请注明原文地址: https://ju.6miu.com/read-39854.html

    最新回复(0)