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

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_22804827/article/details/61915760

在自己撸了一遍自定义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()方法时需要在子线程中,因为在CustomCallAdapteradapt()方法中有执行call.execute(),这会用于网络请求,如果执行contributors3()方法时需要不在子线程中就会出现android.os.NetworkOnMainThreadException

展开阅读全文

没有更多推荐了,返回首页