目录
序章
首先引入依赖
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
在原理之前,我们先来回忆一下Retrofit的基本使用
1、定义接口
interface MyService { @GET("gallery/{imageType}/response") fun getImages(@Path("imageType") imageType: String): Call<List<String>> }
2、构建Retrofit,创建网络请求接口类实例
val retrofit = Retrofit.Builder() .baseUrl(BASE_URL) .build() val myService = retrofit.create(MyService::class.java)
3、生成Call,执行请求
val resp = myService.getImages("banner") resp.enqueue(object : Callback<List<String>> { override fun onResponse(call: Call<List<String>>, response: Response<List<String>>) { TODO("Not yet implemented") } override fun onFailure(call: Call<List<String>>, t: Throwable) { TODO("Not yet implemented") } })
这样一个基本的网络请求就搞定了,使用很简洁,正是因为其内部使用了大量的设计模式和优秀的架构设计,才得以使其如此方便地进行网络请求,下面我们就一起来探索探索Retrofit的设计之美。
Retrofit构建过程
使用了建造者模式通过内部静态类Builder构建一个Retrofit实例,这里只列出了部分方法,其他类似
public static final class Builder { private final Platform platform; // 网络请求工厂,工厂方法模式 private @Nullable okhttp3.Call.Factory callFactory; // 网络请求地址 private @Nullable HttpUrl baseUrl; // 数据转换器工厂的集合 private final List<Converter.Factory> converterFactories = new ArrayList<>(); // 网络请求适配器工厂的集合,默认是ExecutorCallAdapterFactory private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(); // 回调方法执行器,用于切换线程 private @Nullable Executor callbackExecutor; // 一个开关,为true则会缓存创建的ServiceMethod private boolean validateEagerly; //...... public Builder baseUrl(String baseUrl) { Objects.requireNonNull(baseUrl, "baseUrl == null"); return baseUrl(HttpUrl.get(baseUrl)); } public Builder baseUrl(HttpUrl baseUrl) { Objects.requireNonNull(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; } // 将一个含有Gson对象实例的GsonConverterFactory放入数据转换器工厂 public Builder addConverterFactory(Converter.Factory factory) { converterFactories.add(Objects.requireNonNull(factory, "factory == null")); return this; } //...... }
通过build,我们上面Builder类中的参数对象都配置到了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) { 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.addAll(platform.defaultCallAdapterFactories(callbackExecutor)); // Make a defensive copy of the converters. List<Converter.Factory> converterFactories = new ArrayList<>( 1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize()); // 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); converterFactories.addAll(platform.defaultConverterFactories()); return new Retrofit( callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); }
创建网络请求接口实例过程
使用动态代理的方式拿到所有注解配置后,创建网络请求接口实例。
public <T> T create(final Class<T> service) { validateServiceInterface(service); return (T) Proxy.newProxyInstance( service.getClassLoader(), new Class<?>[] {service}, new InvocationHandler() { private final Platform platform = Platform.get(); private final Object[] emptyArgs = new Object[0]; @Override public @Nullable 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); } args = args != null ? args : emptyArgs; return platform.isDefaultMethod(method) ? platform.invokeDefaultMethod(method, service, proxy, args) : loadServiceMethod(method).invoke(args); } }); }
跟踪 loadServiceMethod,parseAnnotations解析注解配置得到ServiceMethod,然后加入到serviceMethodCache缓存中,是一个ConcurrentHashMap。
ServiceMethod<?> loadServiceMethod(Method method) { ServiceMethod<?> result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = ServiceMethod.parseAnnotations(this, method); serviceMethodCache.put(method, result); } } return result; }
abstract class ServiceMethod<T> { static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError( method, "Method return type must not include a type variable or wildcard: %s", returnType); } if (returnType == void.class) { throw methodError(method, "Service methods cannot return void."); } return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); } abstract @Nullable T invoke(Object[] args); }
执行请求过程
public void enqueue(final Callback<T> callback) { Objects.requireNonNull(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 { // 创建一个OkHttp的Request对象请求 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) { throwIfFatal(e); callFailure(e); return; } try { callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { throwIfFatal(t); t.printStackTrace(); // TODO this is not great } } @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) { throwIfFatal(t); t.printStackTrace(); // TODO this is not great } } }); }
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException { ResponseBody rawBody = rawResponse.body(); // Remove the body's source (the only stateful object) so we can pass the response along. rawResponse = rawResponse .newBuilder() .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())) .build(); int code = rawResponse.code(); // 根据响应返回的状态码进行处理 if (code < 200 || code >= 300) { try { // Buffer the entire body to avoid future I/O. ResponseBody bufferedBody = Utils.buffer(rawBody); return Response.error(bufferedBody, rawResponse); } finally { rawBody.close(); } } if (code == 204 || code == 205) { rawBody.close(); return Response.success(null, rawResponse); } ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody); try { // 将响应体转为Java对象 T body = responseConverter.convert(catchingBody); return Response.success(body, rawResponse); } catch (RuntimeException e) { // If the underlying source threw an exception, propagate that rather than indicating it was // a runtime exception. catchingBody.throwIfCaught(); throw e; } }
总结
首先,使用建造者模式通过Builder构建一个Retrofit实例,Builder类中的参数对象都配置到Retrofit对象中,然后使用动态代理的方式拿到所有注解配置后,创建网络请求接口实例,生成OkHttp请求,通过callAdapterFactory找到对应的执行器,比如RxJava2CallAdapterFactory,最后通过ConverterFactory将返回数据解析成JavaBean,使用者只需关心请求参数,内部实现由Retrofit封装完成,底层请求还是基于okhttp实现的。