Retrofit2源码分析

作者: 倒转流年丶 | 来源:发表于2017-06-01 14:56 被阅读41次

官方传送门

本文基于compile 'com.squareup.retrofit2:retrofit:2.2.0'分析

1.概述

Retrofit应该是现在最火的网络请求框架,它是基于okhttp的封装,非常适合restful url格式的请求,可以使用注解实现很多功能。

2.基本用法

public interface IApi {
    @POST("/toutiao/index")
    Call<ResponseBody> getTopNews(@QueryMap Map<String, String> params);
}
// 构造Retrofit
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(Constants.BASE_URL)
        .client(new OkHttpClient())
        .build();
Map<String, String> params = new HashMap<>();
params.put("type", "top");
params.put("key", "52880cdc1ede6a63d0be1f1816f136a7");
// 动态生成代理对象
IApi api = retrofit.create(IApi.class);
// 生成OkhttpCall的代理对象
retrofit2.Call<ResponseBody> call = api.getTopNews(params);
// 异步执行
call.enqueue(new retrofit2.Callback<ResponseBody>() {
    @Override
    public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
        if (response.isSuccessful()) {
            try {
                   Log.e(TAG, "onResponse: " + response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    @Override
    public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {
        Log.e(TAG, "onFailure: " + t.getMessage());
    }
});

3.源码分析

1.构造者模式创建Retrofit对象

  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) {
        // 就是MainThreadExecutor,执行在主线程
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      // 这里加了一个默认的ExecutorCallAdapterFactory,platform对应的实现就是 Android
      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);
}

2.通过动态代理得到接口实例,这里涉及了动态代理,可以参考java的动态代理机制详解

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();
          // 当动态代理对象调用方法时,这个方法的调用就会被转发为由      
          // InvocationHandler这个接口的 invoke 方法来进行调用
          @Override public Object invoke(Object proxy, Method method, 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);
            }
            // 将method包装成ServiceMethod
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            // 构造OkHttpCall
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            // 将OkHttpCall进行代理包装
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
}

3.看下loadServiceMethod方法

ServiceMethod<?, ?> loadServiceMethod(Method method) {
     // 从缓存中取ServiceMethod
    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;
}

4.再看下ServiceMethod内部类Builder中的build方法

Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

    public ServiceMethod build() {
      // 创建CallAdapter,通过ExecutorCallAdapterFactory的get方法获得
      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?");
      }
      // 创建Converter,默认是BuiltInConverters
      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);
}

ServiceMethod中确定了callAdapter,通过ExecutorCallAdapterFactory的get方法获得,根据接口返回值确定了responseConverter,解析方法上的注解拿到初步的url,解析参数中的注解拿到构建RequestBody所需的各种信息,最终调用toRequest的方法完成Request的构建。

5.构造OkHttpCall

OkHttpCall(ServiceMethod<T, ?> serviceMethod, Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
}

6.最后是调用callAdapter的adapt方法,上面有说到callAdapter是通过ExecutorCallAdapterFactory的get方法获得,我们看一下它的get方法

@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,再看下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) {
      if (callback == null) throw new NullPointerException("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();
    }
  }

这里ExecutorCallbackCall封装了call,这里的delegate是OkHttpCall,然后将回调通过callbackExecutor回调到主线程中,

7.执行call,就是调用OkHttpCall的enqueue方法

@Override public void enqueue(final Callback<T> callback) {
    if (callback == null) throw new NullPointerException("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 {
          // 创建okhttp3.call
          call = rawCall = createRawCall();
        } catch (Throwable 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)
          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 {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

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

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

其实就是创建了一个okhttp3的call,然后执行它的enqueue方法

看一下okhttp3.call的创建方法

private okhttp3.Call createRawCall() throws IOException {
    // 创建request
    Request request = serviceMethod.toRequest(args);
    // 这里其实就是一个RealCall
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
}

到这里就是okhttp去处理请求,了解okhttp的执行过程可以参考okhttp源码分析

总结

这里总结下Retrofit2的执行流程

1.构造Retrofit,配置基本参数(如url、client、converterFactory、callAdapterFactory等)
2.利用Java的动态代理拿到定义接口的实现类
3.调用接口方法,InvocationHandler的invoke方法调用,构造ServiceMethod,获取注解及参数信息,通过toRequest转化为okhttp3.Request,然后将Request转化为okhttp3.Call,最后通过callAdapter对Call进行装饰返回
4.调用okhhtp.Call的enqueue执行请求

参考

Retrofit2 完全解析 探索与okhttp之间的关系

相关文章

网友评论

    本文标题:Retrofit2源码分析

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