拆轮子系列--Retrofit2源码分析

作者: a49f87ef5d4f | 来源:发表于2018-08-16 13:27 被阅读2次

    0.前言

    Retrofit是一个基于okhttp的网络请求框架,相当于对于okhttp的一次封装,同理,也是square公司出的,square出品,必属精品,最近有时间,分析仪下它的工作流程,

    1.基本使用

      interface TestService
        {
    
            @GET("/")
            fun test(): Call<String>
        }
        
    class ResponseConvertFactory : Converter.Factory()
        {
            override fun responseBodyConverter(type: Type?, annotations: Array<out Annotation>?, retrofit: Retrofit?): Converter<ResponseBody, String>?
            {
                return Converter<ResponseBody, String> {
                    it.string()
                }
    
            }
    
            override fun stringConverter(type: Type?, annotations: Array<out Annotation>?, retrofit: Retrofit?): Converter<*, String>?
            {
                return super.stringConverter(type, annotations, retrofit)
            }
        }
    
    
     val retrofit = Retrofit.Builder().baseUrl("http://www.baidu.com")
                    .addConverterFactory(ResponseConvertFactory())
                    .build()
            val testService = retrofit.create(TestService::class.java)
            val call = testService.test()
            call.enqueue(object : Callback<String>
            {
                override fun onFailure(call: Call<String>?, t: Throwable?)
                {
    
                }
    
                override fun onResponse(call: Call<String>?, response: Response<String>?)
                {
                    println("response is ${response?.body()}")
                }
    
            })    
    

    这是一个简单的异步http get请求,由于只分析流程,由简单的进入就行了,个人认为看代码了解流程和其设计模式才是最重要的,不需要扣的太厉害。

    2.Retrofit的创建

    Retrofit的创建采用的建造者模式

    val retrofit = Retrofit.Builder().baseUrl("http://www.baidu.com")
                    .addConverterFactory(ResponseConvertFactory())
                    .build()
    

    直接看Retrofit.Builder的build方法

     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> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
          callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    
          // Make a defensive copy of the converters.
          List<Converter.Factory> converterFactories =
              new ArrayList<>(1 + this.converterFactories.size());
    
          // Add the built-in converter factory first. This prevents overriding its behavior but also
          // ensures correct behavior when using converters that consume all types.
          converterFactories.add(new BuiltInConverters());
          converterFactories.addAll(this.converterFactories);
    
          return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
              unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
        }
    

    这里传入了一个CallAdapter.Factory的list,里面的数据是Builder里的calladapter.Factory的list,也就是你在addCallAdapterFactory()方法中传入的参数,这里传入的factory会放入builder的calladapter.Factory的list里,然后又放入了一个默认的calladapterfactory,这个factory是platform的参数,而这个platform是在实例化Builder的时候传入的

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

    如果是跑在android系统,那么返回的就会是Android,看一Android

    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);
          }
        }
      }
    

    可以看到platform返回的CallAdapterFactory就是ExecutorCallAdapterFactory。关于他的作用稍后再谈。

    还有一个Convert.Factory的list,这里是先加入了一个BuiltInConverters,然后放入存在Builder里的Convert.Factory的list,Convert.Factory主要是用来生成Convert来对http请求体和响应报文进行转换。

    2.发行请求前的准备

           val testService = retrofit.create(TestService::class.java)
            val call = testService.test()
    

    通过这两个方法,生成了一个实现TestService接口的实例,调用这个接口的方法返回一个Call。接下来就看看这是怎么做的,如何为接口生成了一个实例,还有怎么生成的Call。

    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.adapt(okHttpCall);
              }
            });
      }
    

    well well,很明显,这是一个动态代理,如果对动态代理不清楚的,可以参考我之前的文章
    拆轮子系列--动态代理。通过动态代理实现了一个实现接口的代理类,接下来看InvocationHandler,如果方法不是来自接口而是object的方法,那么就直接调用,如果是来自接口,那么可以看到先生成了一个serviceMethod,看一下loadServiceMethod方法

    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;
      }
    

    很简单,如果缓存有,就取出一个ServiceMethod,否则就创建一个ServiceMethod,并添加到缓存,还是建造者模式,看一下ServiceMethod.Builder的build方法

     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);
          }
    
          if (httpMethod == null) {
            throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
          }
    
          if (!hasBody) {
            if (isMultipart) {
              throw methodError(
                  "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
            }
            if (isFormEncoded) {
              throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
                  + "request body (e.g., @POST).");
            }
          }
    
          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);
          }
    
          if (relativeUrl == null && !gotUrl) {
            throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
          }
          if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
            throw methodError("Non-body HTTP method cannot contain @Body.");
          }
          if (isFormEncoded && !gotField) {
            throw methodError("Form-encoded method must contain at least one @Field.");
          }
          if (isMultipart && !gotPart) {
            throw methodError("Multipart method must contain at least one @Part.");
          }
    
          return new ServiceMethod<>(this);
        }
    

    先看一下createCallAdapter这个方法

     private CallAdapter<T, R> createCallAdapter() {
          Type returnType = method.getGenericReturnType();
          if (Utils.hasUnresolvableType(returnType)) {
            throw methodError(
                "Method return type must not include a type variable or wildcard: %s", returnType);
          }
          if (returnType == void.class) {
            throw methodError("Service methods cannot return void.");
          }
          Annotation[] annotations = method.getAnnotations();
          try {
            //noinspection unchecked
            return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
          } catch (RuntimeException e) { // Wide exception range because factories are user code.
            throw methodError(e, "Unable to create call adapter for %s", returnType);
          }
        }
    

    根据method返回值的Type和注解,调用retrofit的callAdapter返回Calladapter,看一下Retrofit的calladapter方法。

    public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
        return nextCallAdapter(null, returnType, annotations);
      }
      
      public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
          Annotation[] annotations) {
        checkNotNull(returnType, "returnType == null");
        checkNotNull(annotations, "annotations == null");
    
        int start = callAdapterFactories.indexOf(skipPast) + 1;
        for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
          CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
          if (adapter != null) {
            return adapter;
          }
        }
    
        StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
            .append(returnType)
            .append(".\n");
        if (skipPast != null) {
          builder.append("  Skipped:");
          for (int i = 0; i < start; i++) {
            builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
          }
          builder.append('\n');
        }
        builder.append("  Tried:");
        for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
          builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
        }
        throw new IllegalArgumentException(builder.toString());
      }
    

    言简意赅,遍历Retrofit的CallAdapterFactory list,找到符合要求的calladapter就返回,所以还记得calladapterfactory list的顺序吧,默认的calladapterfactory也就是ExecutorCallAdapterFactory是放在最后的,所以如果你在构建Retrofit的时候添加了别的Calladapter,如果符合条件,是会拦截。RxJavaCallAdapterFactory.create()这个眼熟吧,就是因为它最终返回的是Observable而不是Call。其实这个CallAdapter的作用就是讲OkhttpCall转化为其他数据结构,默认的就是将OkhttpCall转换为ExecutorCallbackCall。
    再回到build方法

    responseConverter = createResponseConverter();
    

    和返回CallAdapter差不多,只不过这是返回的ResponseConvert
    接下来

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

    遍历方法注解得到相应参数,具体就不说了。

    然后又生成了一个OkhttpCall

    OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
    

    你会发现这个OkhttpCall实现了OkHttp的call接口,看它的enque方法

    @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) {
              throwIfFatal(t);
              failure = creationFailure = t;
            }
          }
        }
    
        if (failure != null) {
          callback.onFailure(this, failure);
          return;
        }
    
        if (canceled) {
          call.cancel();
        }
    
        call.enqueue(new okhttp3.Callback() {
          @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response<T> response;
            try {
              response = parseResponse(rawResponse);
            } catch (Throwable e) {
              callFailure(e);
              return;
            }
    
            try {
              callback.onResponse(OkHttpCall.this, response);
            } catch (Throwable t) {
              t.printStackTrace();
            }
          }
    
          @Override public void onFailure(okhttp3.Call call, IOException e) {
            callFailure(e);
          }
    
          private void callFailure(Throwable e) {
            try {
              callback.onFailure(OkHttpCall.this, e);
            } catch (Throwable t) {
              t.printStackTrace();
            }
          }
        });
      }
    

    这里就是生成了一个Okhttp的call,然后接着就是okhttp的网络请求流程了,如果okhttp不熟悉可以看我之前的文章拆轮子系列--okhttp3源码分析

    重新回到invaoctaionhandler,最后调用了serviceMethod.adapte方法,

    T adapt(Call<R> call) {
        return callAdapter.adapt(call);
      }
    

    可以看到就是调用了calladapter的adapt方法,前面说了默认的calladapter是ExecutorCallAdapterFactory制造的

    final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
      final Executor callbackExecutor;
    
      ExecutorCallAdapterFactory(Executor callbackExecutor) {
        this.callbackExecutor = callbackExecutor;
      }
    
      @Override
      public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        if (getRawType(returnType) != Call.class) {
          return null;
        }
        final Type responseType = Utils.getCallResponseType(returnType);
        return new CallAdapter<Object, Call<?>>() {
          @Override public Type responseType() {
            return responseType;
          }
    
          @Override public Call<Object> adapt(Call<Object> call) {
            return new ExecutorCallbackCall<>(callbackExecutor, call);
          }
        };
      }
    

    可以看到返回了一个匿名内部类,他的adapt方法实际返回了ExecutorCallbackCall

    static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;
        final Call<T> delegate;
    
        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
          this.callbackExecutor = callbackExecutor;
          this.delegate = delegate;
        }
    
        @Override public void enqueue(final Callback<T> callback) {
          checkNotNull(callback, "callback == null");
    
          delegate.enqueue(new Callback<T>() {
            @Override public void onResponse(Call<T> call, final Response<T> response) {
              callbackExecutor.execute(new Runnable() {
                @Override public void run() {
                  if (delegate.isCanceled()) {
                    // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                    callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                  } else {
                    callback.onResponse(ExecutorCallbackCall.this, response);
                  }
                }
              });
            }
    
            @Override public void onFailure(Call<T> call, final Throwable t) {
              callbackExecutor.execute(new Runnable() {
                @Override public void run() {
                  callback.onFailure(ExecutorCallbackCall.this, t);
                }
              });
            }
          });
        }
    
        @Override public boolean isExecuted() {
          return delegate.isExecuted();
        }
    
        @Override public Response<T> execute() throws IOException {
          return delegate.execute();
        }
    
        @Override public void cancel() {
          delegate.cancel();
        }
    
        @Override public boolean isCanceled() {
          return delegate.isCanceled();
        }
    
        @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
        @Override public Call<T> clone() {
          return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
        }
    
        @Override public Request request() {
          return delegate.request();
        }
      }
    

    可以发现这个也实现了Okhttp的call接口,同时还持有了一个callbackexecutor和之前生成的okhttpcall,可以发现调用它的enqueu方法真正执行网络请求的就是okhttpcall,而这个callbackexecutor实际是

    static class MainThreadExecutor implements Executor {
          private final Handler handler = new Handler(Looper.getMainLooper());
    
          @Override public void execute(Runnable r) {
            handler.post(r);
          }
        }
    

    很明显,通过这种方式保证了回调结果在主线程。

    (盗张图帮助理解)
    图片来自

    image image

    关注我的公众号

    相关文章

      网友评论

        本文标题:拆轮子系列--Retrofit2源码分析

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