4.4 Retrofit 源码解析

Retrofit是很多公司常用的网络框架。也是Square公司出品,也属于精品之一。Retrofit的内核是okhttp,Retrofit只负责外层请求的封装,其真正去请求网络的任务依然是okhttp.这样的好处就是简单请求的配置。

基本使用:

	Retrofit retrofit = new Retrofit.Builder()
		.baseUrl("http://www.xxxx.com") // 添加请求地址
		.addConverterFactory(GsonConverterFactory.create())//使用gson库解析
		.build();
	IFoodService iFoodService = retrofit.create(IFoodService.class);
	Call<ResponseBody> call = iFoodService.getFoodList();
	call.enqueue(new Callback<ResponseBody>() {
	.........
	}

Retrofit.Builder()

Retrofit使用大量的设计模式,比如主对象使用了建造者模式,构造里调用了Platform.get().一个独立的类,一直可以追踪到findPlatform(),通过类加载器的形式,去加载Android平台的Build,这类事系统属性类,包含系统的版本各种信息。如果没有异常,就证明现在是Android平台,创建一个Android类。

 public Builder() {
      this(Platform.get());
    }
private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
   ...
  }



static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

Android类继承Platform,而且还有几个重要的方法,defaultCallbackExecutor默认回调的执行器对象,返回一个MainThreadExecutor,而这哥们实现了Exector,而且还用的主线程的Looper,怪不得Retrofit的回调结果是在主线程呢,原因就是它了。

baseUrl

用过retrofit的同学都知道,baseUrl的链接有时候也会踩坑,baseUrl的尾必须得用“/”结尾。究其原因,看代码,checkNotNull检查不为null.

  /**
     * Set the API base URL.
     *
     * @see #baseUrl(HttpUrl)
     */
    public Builder baseUrl(String baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      HttpUrl httpUrl = HttpUrl.parse(baseUrl);
      if (httpUrl == null) {
        throw new IllegalArgumentException("Illegal URL: " + baseUrl);
      }
      return baseUrl(httpUrl);
    }

 public Builder baseUrl(HttpUrl baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      List<String> pathSegments = baseUrl.pathSegments();
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

build

建造者模式调用build方法,一般就要创建对象了。先创建一个callFactory,其实是OkhttpClient对象,再往下默认的回调执行器对象callbackExecutor,就是从platform里获取的,还记得上面说过嘛。
适配器工厂对象,
转换器工厂对象
然后准备这些对象后,就创建了一个Retrofit对象,把所有的配置就准备好。


  /**
     * Create the {@link Retrofit} instance using the configured values.
     * <p>
     * Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
     * OkHttpClient} will be created and used.
     */
    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }
  }


  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
      @Nullable Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
    this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }

Create 创建接口的实例

create也是一个很重要的方法,它根据接口的方法描述,创建不同请求方法,解析注解,解析参数,然后存入到容器里。这里使用动态代理的形式解析每个方法的各个参数,封装成请求对象,来去网络获取数据。
eagerlyValidateMethods 验证方法,然后去加载方法loadServiceMethod,

public <T> T create(final Class<T> service) {
	// 验证接口合法性
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
    	//验证接口的方法且加载它
      eagerlyValidateMethods(service);
    }
    // 通过动态代理来实例接口对象
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }


 private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }
//serviceMethodCache是一个map集合,它保存方法名和ServiceMethod对象,
//new ServiceMethod.Builder<>(this, method).build();干嘛了呢,
// 大家看看如下代码,这都是请求的配置信息
 // ServiceMethod(Builder<R, T> builder) {
 //   this.callFactory = builder.retrofit.callFactory(); okhttpclient对象
 //   this.callAdapter = builder.callAdapter; // 适配器对象
 //   this.baseUrl = builder.retrofit.baseUrl(); 请求链接
 //   this.responseConverter = builder.responseConverter;响应体的转换器
 //   this.httpMethod = builder.httpMethod; 请求方法
 //   this.relativeUrl = builder.relativeUrl; 请求的部分url
  //  this.headers = builder.headers; 头部信息
  //  this.contentType = builder.contentType; 请求类型
  //  this.hasBody = builder.hasBody; 是否有请求体
 //   this.isFormEncoded = builder.isFormEncoded; 是否是表单类型
 //   this.isMultipart = builder.isMultipart;  多类型数据
  //  this.parameterHandlers = builder.parameterHandlers; 参数
 // }
  ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
//parseMethodAnnotation 解析注解
//parseParameter 解析参数
 public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
  

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

     。。。。。
      return new ServiceMethod<>(this);
    }


 private void parseMethodAnnotation(Annotation annotation) {
      if (annotation instanceof DELETE) {
        parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
      } else if (annotation instanceof GET) {
        parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
      } 
      。。。。。。
    }




parseParameter是解析参数,迭代注解数组,parseParameterAnnotation解析具体的参数,可以看到根据不同的参数类型进行判断,类型很多,拿一个作为列子,query类型最终返回了一个 return new ParameterHandler.Query<>(name, converter, encoded).iterable();这个对象其实还是ParameterHandler的子类,如图,这个对象有好多子类。可以他们有共同点,就是这些都是参数的注解。
在这里插入图片描述


    private ParameterHandler<?> parseParameter(
        int p, Type parameterType, Annotation[] annotations) {
      ParameterHandler<?> result = null;
      for (Annotation annotation : annotations) {
        ParameterHandler<?> annotationAction = parseParameterAnnotation(
            p, parameterType, annotations, annotation);
 
      return result;
    }
 	private ParameterHandler<?> parseParameterAnnotation(
        int p, Type type, Annotation[] annotations, Annotation annotation) {
     
       .....
       
      } else if (annotation instanceof Query) {
        Query query = (Query) annotation;
        String name = query.value();
        boolean encoded = query.encoded();

        Class<?> rawParameterType = Utils.getRawType(type);
        gotQuery = true;
        if (Iterable.class.isAssignableFrom(rawParameterType)) {
          if (!(type instanceof ParameterizedType)) {
            throw parameterError(p, rawParameterType.getSimpleName()
                + " must include generic type (e.g., "
                + rawParameterType.getSimpleName()
                + "<String>)");
          }
          ParameterizedType parameterizedType = (ParameterizedType) type;
          Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
          Converter<?, String> converter =
              retrofit.stringConverter(iterableType, annotations);
          return new ParameterHandler.Query<>(name, converter, encoded).iterable();
        

      } else if (annotation instanceof QueryName) {
      
      } else if (annotation instanceof QueryMap) {
       
      } else if (annotation instanceof Header) {
      
      } else if (annotation instanceof HeaderMap) {
        
      } else if (annotation instanceof Field) {
       
      } else if (annotation instanceof FieldMap) {
        
      } else if (annotation instanceof Body) {
        
      return null; // Not a Retrofit annotation.
    }

OKHttpCall 回调逻辑

这个对象干嘛的呢,它是接口实例返回的对象。
Call call = iFoodService.getFoodList();
这个Call其实就是OkHttpCall,是Call的实现类。
在调用Create方法的创建了对象,这也是调用enqueue的逻辑。

大家注意传入callBack对象的逻辑,给大家标记出来。一共4处,在2.3.4处,都是通过call.enquque调用的,这个call在哪赋值的呢, call = rawCall = createRawCall(); 进入方法,可以看到这个对象已经由okHttp接管了,所以这个地方结果回调其实都是由okhttp来做的。

@Override public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
    	//标记1
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }

    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
        //标记2
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callFailure(Throwable e) {
        try {
        //标记3
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callSuccess(Response<T> response) {
        try {
        //标记4
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }


/**
*  这里面callFactory其实就是okHttpClient的对象,还记得retrofit主对象调用build方法,可以回去看看,
*  最终得到的Call,其实就是Okhttp的ReadlCall
**/
  private okhttp3.Call createRawCall() throws IOException {
    Request request = serviceMethod.toRequest(args);
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值