美文网首页
Retrofit2自定义CallAdapter

Retrofit2自定义CallAdapter

作者: 有没有口罩给我一个 | 来源:发表于2017-07-02 17:41 被阅读0次

    前言

    本节将介绍如何自定一个CallAdapter,通过源码的级别讲解Retrofit2的CallAdapter。

    先看一下CallAdapter接口定义及各方法的作用,已上注释:
    public interface CallAdapter<R, T> {
      //返回此适配器将HTTP响应正文转换为Java时使用的值类型对象。 例如, Call <Repo>的响应类型是Repo。 这个类型用于准备传递给adapt的call。
      Type responseType();
    
    //这个方法很重要,会在 Retrofit的create(final Class<T> service)方法中被调用,并把okHttpCall即Call传进来serviceMethod.callAdapter.adapt(okHttpCall),接下来我们可以对Call进行操作了
      T adapt(Call<R> call);
    
    //CallAdapter工厂,retrofit默认的DefaultCallAdapterFactory其中不对Call做处理,是直接返回Call。
    abstract class Factory {
    // 在这个方法中判断是否是我们支持的类型,returnType 即Call<Requestbody>和`Observable<Requestbody>`
    // RxJavaCallAdapterFactory 就是判断returnType是不是Observable<?> 类型
    // 不支持时返回null
    //返回值必须是Custom并且带有泛型(参数类型),根据APIService接口中的方法返回值,确定returnType,如: CustomCall<String> getCategories();,那确定returnType就是CustomCall<String>
    public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
        Retrofit retrofit);
    
     // 用于获取泛型的参数 如 Call<Requestbody> 中 Requestbody
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }
    
     // 用于获取泛型的原始类型 如 Call<Requestbody> 中的 Call
    //  如Call<Requestbody>拿到的原始类型就是Call
    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
          }
    
       }
     }
    

    看看Retrofit默认使用的DefaultCallAdapterFactory,默认不做处理直接返回Call:

    final class DefaultCallAdapterFactory extends CallAdapter.Factory {
    
    static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();
    
    //重要的方法,注意看哥们
    @Override
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    //判断APIService接口方法的返回值,是否为Call,如果返回值不是Call,那么不做处理,返回null就是不处理。
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    
    //这里和我们在上面的介绍是一样的,底层也是调用了getParameterUpperBound(0, (ParameterizedType) returnType)方法,获取泛型的参数,即返回值类型,以便后期Converter做转换操作,
    final Type responseType = Utils.getCallResponseType(returnType);
    
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }
    //直接返回Call
      @Override public Call<Object> adapt(Call<Object> call) {
        return call;
      }
    };
    }
    }
    
    没有demo说再多也没用,下面来自定义一个叫CustomCallAdapter:
    • 第一步定义CustomCall,专门处理Call的数据

       public static class CustomCall<R> {
      
      public final Call<R> call;
      
      public CustomCall(Call<R> call) {
          this.call = call;
      }
      
      public R get() throws IOException {
            return call.execute().body();
            }
      }
      
    • 第二步定义CustomCallAdapter实现 Call<T> 到 CustomCall<T>的转换,这里需要注意的是最后的泛型,是我们要返回的类型:

      public class CustomCallAdapter implements CallAdapter<R, CustomCall<R>> {
      private final Type responseType;
      
      public CustomCallAdapter(Type responseType) {
        this.responseType = responseType;
      }
      
      /**
       * 真正数据的类型,如Call<T> 中的 T,这个T会作为  Converter.Factory.responseConverter的第一个参数
       *
       * @return
       */
      @Override
      public Type responseType() {
        return responseType;
        }
      
      @Override
        public CustomCall<R> adapt(Call<R> call) {
            return new CustomCall<>(call);
          }
      }
      
    • 第三部提供一个CustomCallAdapterFactory用于向Retrofit提供CustomCallAdapter:

      public class CustomCallAdapterFactory extends CallAdapter.Factory {
      
      public static CustomCallAdapterFactory create() {
        return new CustomCallAdapterFactory();
      }
      
      @Nullable
      @Override
      public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
      
        //获取原始类型
        Class<?> rawType = getRawType(returnType);
      
        //返回值必须是Custom并且带有泛型(参数类型),根据APIService接口中的方法返回值,确定returnType
        //如 CustomCall<String> getCategories();,那确定returnType就是CustomCall<String>
        if (rawType == CustomCall.class && returnType instanceof ParameterizedType) {
            Type callReturnType = getParameterUpperBound(0, (ParameterizedType) returnType);
            return new CustomCallAdapter(callReturnType);
        }
      
        return null;
        }
      }
      
    • 第四步使用addCallAdapterFactory向Retrofit注册CustomCallAdapterFactory

    Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(GitHubService.GLABALURL)
                .addCallAdapterFactory(CustomCallAdapterFactory.create())
                .addConverterFactory(StringConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(client)
                .build();
    

    注: addCallAdapterFactory与addConverterFactory同理,也有先后顺序。

    最后来看看retrofit执行流程:

    create(final Class<T> service)---> loadServiceMethod(method)---->
    ServiceMethod.Builder..build()--->createCallAdapter()--->
    method.getGenericReturnType()--->callAdapter(returnType,   annotations)--->
    nextCallAdapter(null, returnType, annotations)--->
    createResponseConverter()--->method.getAnnotations()--->
    etrofit.responseBodyConverter(responseType, annotations)--->
    nextResponseBodyConverter(null, type, annotations)
    

    上面的是retrofit的执行流程,按照上面的步骤可以查看所有的源代码。

    本节就到这里,下一节将会讲解,Converter 的自定义。可能文中会有疏漏或错误,敬请指正,谢谢大家!

    相关文章

      网友评论

          本文标题:Retrofit2自定义CallAdapter

          本文链接:https://www.haomeiwen.com/subject/ywggcxtx.html