Retrofit源码导读

xiaoxiao2021-02-28  12

一、Retrofit简介 Retrofit是由 Square公司 出品的针对于Android和Java的类型安全的Http客户端,网络服务基于 OkHttp  。  二、代码阅读前基础知识准备 在阅读Retrofit源代码前需要了解以下方面的基础知识点。 2.1 android耗时操作的处理套路 在Android进行耗时操作时,通常会将耗时任务放在子线程或线程池中执行,执行完毕后的结果再通过回调返回到主线程中,在回调过程中伴随有线程的切换。 Android中这种耗时操作的处理套路,可以参考在子线程中对UI界面中进行更新,一般使用Handler来进行回调和切换线程。 Retrofit在处理耗时的网络请求操作过程中也采用了这样的套路,只是Retrofit采用的套路比较深。Retrofit网络请求框架的基本流程如下,图下的Executor一般采用OKhttp库充当,在OKhttp模块内有线程池,可以不断接收网络请求线程。网络请求的执行结果被解析后返回,返回时一般使用Retrofit中的 defaultCallbackExecutor进行切换线程的操作2.2 设计模式 Retrofit在设计中采用的大量的设计模式,众多的设计模式造就了Retrofit的超级解耦和好用,下面对Retrofit采用的设计模式进行一个大致的列举和说明。 抽象工厂模式 抽象工厂模式属于创建者模型,主要是为了将用户从固定类型的创建过程中解耦出来,隐藏复杂的new操作。 Retrofit中采用的是抽象工厂模式,包括有 okhttp3.Call.Factory,CallAdapter.Factory 和 Converter.Factory。 public interface CallAdapter<T> { Type responseType(); <R> T adapt(Call<R> call); abstract class Factory { public abstract CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit); protected static Type getParameterUpperBound(int index, ParameterizedType type) { return Utils.getParameterUpperBound(index, type); } protected static Class<?> getRawType(Type type) { return Utils.getRawType(type); } } } Retorfit中默认有CallAdapter接口的实现,看Retrofit中的默认实现  final class DefaultCallAdapterFactory extends CallAdapter.Factory { static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory(); @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<Call<?>>() { @Override public Type responseType() { return responseType; } @Override public <R> Call<R> adapt(Call<R> call) { return call; } }; } } 但是一般情况下都是用现在RxJava,所以就有了RxJavaCallAdapterFactory供我们使用。 public final class RxJavaCallAdapterFactory extends CallAdapter.Factory { @Override public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { ...... } CallAdapter<Observable<?>> callAdapter = getCallAdapter(returnType, scheduler); ...... return callAdapter; } private CallAdapter<Observable<?>> getCallAdapter(Type returnType, Scheduler scheduler) { ...... return new SimpleCallAdapter(observableType, scheduler); } RxJavaCallAdapterFactory和DefaultCallAdapterFactory两个具体工厂类生产出来的产品就是SimpleCallAdapter和CallAdapter。 适配器模式 适配器模式将一个类的接口,转化成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。 CallAdapter的作用是调度网络请求,在里面的adapt方法用了适配器模式,将默认的Call适配到客户端想要用的Adapter上。 外观模式(门面模式) 外观模式(门面模式)属于结构性模式,它隐藏了系统的复杂性,为子系统的一组接口提供一个统一的访问接口,这个接口使得子系统更容易被访问或使用。 Retrofit的门面就是 retrofit.create() 另外Retrofit模式还包括享元模式,装饰者模式,建造者模式,动态代理模式和策略模式等等。 三、Retrofit源码分析 一个Retrofit实例 public class LearnRetrofit { public static final String API_URL = "https://api.github.com"; //创建接口 public interface GitHub { @GET("/repos/{owner}/{repo}/contributors") Call<ResponseBody> contributors( @Path("owner") String owner, @Path("repo") String repo); } public static void main(String[] args) throws IOException { //创建Retrofit对象 Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL) .build(); //动态生成一个代理对象 GitHub github = retrofit.create(GitHub.class); //生成一个OKHttpCall的代理对象 Call<ResponseBody> call = github.contributors("square", "retrofit"); //返回结果 Response<ResponseBody> response = call.execute(); //打印数据 System.out.println(response.body().string()); } } 3.1 源码解析之Retrofit对象的创建 Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL) .build(); Retrofit中的创建代码 public Retrofit build() { ... // 创建OkHttp,目前Retrofit只支持OkHttp okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } // 创建Executor,见步骤3 Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } // Make a defensive copy of the adapters and add the default Call adapter. // 对adapters进行保护性拷贝,并且加入默认的call adapter(使用上面创建的Executor来构建,可以认为是把主线程中的Handler传入) // 构建adapterFactories集合,将defaultAdapterFactory加入其中,见步骤4 List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // Make a defensive copy of the converters. // 对converters进行保护性拷贝 // 一般传入的为GsonConverterFactory对象,其作用主要是将json转换成java对象 List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories); //最终完成Retrofit对象构建 return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); } Retrofit代码的创建与两个主要任务: 创建callbackExecutor(内部获取主线程MainLooper来构建Hanlder,其execute方法本质是Handler.post(runnable),待用于线程切换)。构建adapterFactories集合,将defaultAdapterFactory加入其中(ExecutorCallAdapterFactory类,线程切换关键实现,内部持有OkHttp代理delegate,在delegate.enqueue中的onRespond方法内使用刚刚创建的callbackExecutor.execute方法,从而实现线程切换)。 Retrofit代码创建中Executor的获取,从主线程获取Looper后创建Handler,通过Handler.post来完成线程的切换。 static class Android extends Platform { @Override public Executor defaultCallbackExecutor() { // 返回MainThreadExecutor return new Platform.Android.MainThreadExecutor(); } @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) { return new ExecutorCallAdapterFactory(callbackExecutor); } static class MainThreadExecutor implements Executor { // 从主线程得到MainLooper,构建Handler private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { // execute方法本质:通过handler,在主线程上执行该runnable handler.post(r); } } } 线程切换的过程 @Override public void enqueue(final Callback<T> callback) { if (callback == null) throw new NullPointerException("callback == null"); // 子线程中执行,此处的delegate本质是OkHttpCall(主要用于对接OkHttp框架) delegate.enqueue(new Callback<T>() { @Override public void onResponse(final Call<T> call, final Response<T> response) { //该方法本质是调用主线程的Handler执行runnable callbackExecutor.execute(new Runnable() { @Override public void run() { if (delegate.isCanceled()) { // Emulate OkHttp's behavior of throwing/delivering an IOException oncancellation. callback.onFailure(call, new IOException("Canceled")); } else { callback.onResponse(call, response); } } }); } @Override public void onFailure(final Call<T> call, final Throwable t) { // 包裹用户传入的callback,从而实现线程切换 callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(call, t); } }); } }); } 3.2 创建接口实现类 Retrofit.create(Api.class) 创建并返回一个会拦截接口方法的动态代理对象实例,接口方法被调用时,会被其拦截,内部将接口方法适配成HTTP Call,再构造对应的OKHttpCall,这里的OKHttpCall是OKHttp的一个包装类,用它生成OkHttp。最后通过CallAdapter.adapt()转换成Retrofit适用的call delegares(即 ExecutorCallbackCall)。 Api api = retrofit.create(Api.class); // create方法内部实现,返回一个动态代理实例 public <T> T create(final Class<T> service) { ... // 该动态代理会对接口方法进行拦截 return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, // 创建一个InvocationHandler,接口方法被调用时会被拦截调用 new InvocationHandler() { private final Platform platform = Platform.get(); // 当Api接口方法被调用时,会调用invoke方法拦截 @Override public Object invoke(Object proxy, Method method, Object... args) throws Throwable { ... // 通过解析api方法注解、传参,将接口中方法适配成HTTP Call,详解见步骤6 ServiceMethod serviceMethod = loadServiceMethod(method); // 拦截下来之后,内部构建一个okHttpCall OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); // 最后通过callAdapter将okHttpCall转换成为Retrofit适用的call delegates(代理), Android平台默认使用ExecutorCallAdapterFactory,adapt返回ExecutorCallbackCall return serviceMethod.callAdapter.adapt(okHttpCall); } }); } 上述 ServiceMethod 内部主要是将方法中的注解取出,转换成HTTP Call的逻辑,暂且不深究。 3.3 执行http请求 在示例代码中调用call.execute()就会执行http请求,这里的call是OKHttpCall的一个对象。从下面的代码可见,调用了OKHttpCall.execute(),该方法会生成一个okhttp3.Call将任务抛给OKHttp,完了调用parseResponse,用Converter将okhttp3.Response转换成我们在范型中指定的类型Response<ResponseBody> response = call.execute(),我指定了okhttp3.ResonseBody。然后返回结果。如果我在构造Retrofit时提供了GsonConverter,addConverterFactory(GsonConverterFactory.create())那么上面的T body = responseConverter.convert(catchingBody);responseConverter就是GsonConverter。 final class OkHttpCall<T> implements Call<T> { //核心成员变量 private final okhttp3.Call.Factory callFactory; private final RequestFactory requestFactory; private final Object[] args; private final Converter<ResponseBody, T> responseConverter; //核心方法 @Override public Response<T> execute() throws IOException { okhttp3.Call call; synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; if (creationFailure != null) { if (creationFailure instanceof IOException) { throw (IOException) creationFailure; } else { throw (RuntimeException) creationFailure; } } call = rawCall; if (call == null) { try { //将任务抛给OKHttp call = rawCall = createRawCall(); } catch (IOException | RuntimeException e) { creationFailure = e; throw e; } } } if (canceled) { call.cancel(); } //转换结果 return parseResponse(call.execute()); } //生成okhttp3.Call private okhttp3.Call createRawCall() throws IOException { //这个callFactory就是OKHttpClient okhttp3.Call call = callFactory.newCall(requestFactory.create(args)); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; } //将okhttp3.Response转换成Response 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) { return Response.success(null, rawResponse); } ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody); try { //这个responseconverter就是默认提供的RequestBodyConverter,当然我们可以替换成自己的converter比如GsonConverter 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; } } 四、Retrofit流程总结 1. Retrofit对象的构建 Retrofit.Builder()...build():①构建OkHttpClient,目前Retrofit仅支持OkHttpClient;②构建Executor:优先根据用户提供的callBackExcecutor来构建,若用户没有提供,则提供defaultCallbackExecutor(其内部会获取MainLooper构建handler,execute方法直接handler.post(runnable),实现在主线程上的操作);③使用executor来构建adapterFactories集合,优先将用户提供的adapterFactory加入到其中,再加上defaultCallAdapterFactory(传入②创建的callbackExecutor,defaultCallAdapterFactory内部持有OkHttpCall,在其enqueue方法中的onResponse方法调用defaultCallbackExecutor.execute方法,从而实现线程切换操作);④最终使用Retrofit构造方法构建Retrofit实例对象 2. Retrofit接口方法的实现方式 retrofit.create(接口名.class):①create方法创建并返回动态代理对象实例,动态代理对象内部会拦截接口方法的调用②动态代理内部通过ServiceMethod将接口方法适配成HTTP Call,再构造对应的OkHttpCall,最后通过CallAdapter转换成Retrofit适用的call delegate(ExecutorCallbackCall)。 3. 使用动态代理(接口实现类)调用接口方法得到Call、使用call.enqueue进行异步请求:①调用接口方法时,动态代理对象(接口实现类)内部拦截;②调用call.enqueue,内部会调用ExecutorCallAdapter的enqueue方法,enqueue中onResponse方法调用defaultCallbackExecutor.execute方法,使用主线程Handler.post(runnable)从而实现线程切换操作。
转载请注明原文地址: https://www.6miu.com/read-1650160.html

最新回复(0)