一、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 { Type responseType(); T adapt(Call 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>() { @Override public Type responseType() { return responseType; }
@Override public Call adapt(Call call) { return call; } }; } }
但是一般情况下都是用现在RxJava,所以就有了RxJavaCallAdapterFactory供我们使用。
public final class RxJavaCallAdapterFactory extends CallAdapter.Factory {
@Override public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { ...... }
CallAdapter> callAdapter = getCallAdapter(returnType, scheduler); ...... return callAdapter; }
private CallAdapter> 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 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 call = github.contributors("square", "retrofit");
//返回结果 Response 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 adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters. // 对converters进行保护性拷贝 // 一般传入的为GsonConverterFactory对象,其作用主要是将json转换成java对象 List converterFactories = new ArrayList<>(this.converterFactories);
//最终完成Retrofit对象构建 return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); }
Retrofit代码的创建与两个主要任务:
  1. 创建callbackExecutor(内部获取主线程MainLooper来构建Hanlder,其execute方法本质是Handler.post(runnable),待用于线程切换)。
  2. 构建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 callback) { if (callback == null) throw new NullPointerException("callback == null"); // 子线程中执行,此处的delegate本质是OkHttpCall(主要用于对接OkHttp框架) delegate.enqueue(new Callback() { @Override public void onResponse(final Call call, final Response 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 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 create(final Class 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 response = call.execute(),我指定了okhttp3.ResonseBody。然后返回结果。如果我在构造Retrofit时提供了GsonConverter,addConverterFactory(GsonConverterFactory.create())那么上面的T body = responseConverter.convert(catchingBody);responseConverter就是GsonConverter。
final class OkHttpCall implements Call { //核心成员变量 private final okhttp3.Call.Factory callFactory; private final RequestFactory requestFactory; private final Object[] args; private final Converter responseConverter;
//核心方法 @Override public Response 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 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)从而实现线程切换操作。

更多相关文章

  1. android Qemu GPS 模块简明分析
  2. Android(安卓)Service两种启动方式详解(总结版)
  3. 几种判断应用(Android(安卓)App)前后台状态的方法
  4. Android热修复原理探索与实践
  5. Android之Activity生命周期浅析(一)
  6. Android中获取控件的宽度以及高度的几种方法
  7. [置顶] Android:在任意位置获取应用程序Context
  8. Android中Handler小例子
  9. Android(安卓)View相关-View的常用方法及使用区别

随机推荐

  1. Android隐藏ListView的滚动条
  2. Android(安卓)Uri转换成真实File路径
  3. Android时间选择器
  4. android ListView TV 通过遥控器上下 smo
  5. android之sqlite用法
  6. Migrating Your Android(安卓)App from E
  7. mount android yaffs image on ubuntu
  8. Android(安卓)TV自定义通用标题栏(组合控
  9. Android中 实现输入框搜索,清楚历史记录
  10. Android实现CoverFlow效果三