retrofit是一种类型安全的HTTP客户端。所谓的类型安全,就是说在运行时不会报类型错误,它会在编译期检查。 要分析它的源码当然是从使用开始说起。在之前的例子中通过Retrofit.create()方法来生成网络请求对象,利用这个对象进行相关的同步或者异步请求。所以从这里开始。
public <T> T create(final Class<T> service) { //验证是否为接口而且是不继承其他接口的接口 Utils.validateServiceInterface(service); if (validateEagerly) { eagerlyValidateMethods(service); } //核心就是动态代理,就是创建一个对象,它会代理service(接口)中的每个方法, //然后把接口中的每个方法通过serviceMethod.callAdapter.adapt(okHttpCall);代替返回相应的结果 //参数一:类加载器,参数二:动态代理代理的是哪些类,参数三 return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { //Anddroid的还是Java8、Java7等 private final Platform platform = Platform.get(); @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. //如果是Object类自有的方法就直接执行 if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } //如果是平台中自有的方法也直接执行 if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } ServiceMethod serviceMethod = loadServiceMethod(method); //call就做了两件事 //一:生成一个真正的OKHTTP的call并且加入请求队列 //二:对返回结果利用之前定义的converter转换后返回给callback OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); //之所以会用adapter的adapt方法主要是为了线程切换(rxjava的转换),这里是把结果切回主线程 return serviceMethod.callAdapter.adapt(okHttpCall); } }); } 复制代码
先关方法的含义已经写到注释里了,因为上面这些核心的就是动态代理,它会代理service中的每个方法,既然是代理接口类的每个方法,那么首先是找到方法 loadServiceMethod(method);
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; } 复制代码
从上面可以看出无非就是之前加载过的话就从缓存中取,没加载过的话就的重新构建并且加入到缓存中。找到方法之后则很自然的要执行这个方法,那就得是OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);通过这步把要执行的方法及参数保存到了OKHTTP的call中,当执行enqueque的时候则真正的用得到的方法和参数请求网络。 在基本使用中,构造完网络请求对象之后,就用这个对象进行实际的网络请求,比如异步的enquue。
@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) { 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(); } } }); } 复制代码
上面代码中最重要的则是 createRawCall() ,也就是创建OKHTTP的call,然后利用这个call调用OKHTTP的enqueque来进行真正的网络请求,同时将返回值返回到callback中。 到这里已经可以拿到网络通信结果了当然是通过 parseResponse(rawResponse) 转换的最终结果,而这个转换则是通过初始化时 addConverterFactory 添加的转换器,为什么不直接返回这个okHttpCall而是还要进行下一步 return serviceMethod.callAdapter.adapt(okHttpCall); 那就得看一下OKHTTP的enqueque做了什么
@Override public void enqueue(Callback responseCallback) { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } captureCallStackTrace(); client.dispatcher().enqueue(new AsyncCall(responseCallback)); } 复制代码
OKHTTP的实现类中的enqueue调用了 client.dispatcher().enqueue(),继续看这个enqueque
synchronized void enqueue(AsyncCall call) { if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) { runningAsyncCalls.add(call); executorService().execute(call); } else { readyAsyncCalls.add(call); } } 复制代码
从这个理可以看出来如果当前发送请求的数量大于 maxRequests (当前源码数量为64),加入队列待执行,如果没到则执行,而执行的代码可以清楚的看到使用executorService().execute(call)。说明在后台线程池中进行的请求和返回。那么到这里就大致的可以推断出return adatp的作用了,那就是 线程切换 。 直接跟进去发现adapt方法是在接口类中,那么我们直接找它的实现类看看,一共有两个即 ExecutorCallAdapterFactory 和 DefaultCallAdapterFactory ,然后再看这两个类在那儿用的,发现是在下面这个方法中调用的
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { if (callbackExecutor != null) { return new ExecutorCallAdapterFactory(callbackExecutor); } return DefaultCallAdapterFactory.INSTANCE; } 复制代码
而这个方法有又是retrofit的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> 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); } } 复制代码
而在这个方法中我们看到需要向方法中传一个callbackExecutor,而这个executor从字面看就是与平台相关的,那么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); } } } 复制代码
从handler.post我们一下子就豁然开朗了。 大框架已经已经说完了,那么那些注解什么时候用的呢,那就得从构造方法和参数入手了,仔细看一下
ServiceMethod.Builder<>(this, method).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); } 复制代码
从上面的源码可以看出首先创建了最后一步需要的callAdapter,然后创建ResponseConverter,也就是通常的将结果转化为Gson等的转换器。然后解析方法注解parseMethodAnnotation(annotation);、解析参数注解parseParameter(p, parameterType, parameterAnnotations)。最后生成的请求和返回所需要的全部参数如下
ServiceMethod(Builder<R, T> builder) { this.callFactory = builder.retrofit.callFactory(); this.callAdapter = builder.callAdapter; this.baseUrl = builder.retrofit.baseUrl(); this.responseConverter = builder.responseConverter; this.httpMethod = builder.httpMethod; this.relativeUrl = builder.relativeUrl; this.headers = builder.headers; this.contentType = builder.contentType; this.hasBody = builder.hasBody; this.isFormEncoded = builder.isFormEncoded; this.isMultipart = builder.isMultipart; this.parameterHandlers = builder.parameterHandlers; } 复制代码