Retrofit2.0源码解析(简版)

来源:互联网 发布:mac官网口红价格 编辑:程序博客网 时间:2024/05/01 18:06

出处:http://www.jianshu.com/p/69a3aff6bfac

Retrofit 是square公司开发的一款对OKHttp进行了进一步封装的网络框架,现在也是android网络请求中非常火的一个网络请求框架,最近在准备面试的时候也刚好复习到了这一块,然后花了几天时间简单地看了下Retrofit2.0源码,分享一下。若有不对的地方,欢迎指正。

Retrofit2.0原理

Retrofit2.0用了动态代理技术,通过解析注解生成Http请求,把请求交给OkHttp,然后通过我们设置的ConverterFactory进行serialization和deserialization,最后通过CallAdapter把结果进行进一步适配,实现了对Rxjava,Guava和java8的支持。


Retrofit2.0所使用的动态代理

在官方给的samples中,我们首先得创建一个retrofit对象,然后通过该对象创建一个我们要代理的实例,即:

 public static final String API_URL = "https://api.github.com"; Retrofit retrofit = new Retrofit.Builder()        .baseUrl(API_URL)        .addConverterFactory(GsonConverterFactory.create())        .build();    // Create an instance of our GitHub API interface. GitHub github = retrofit.create(GitHub.class);

这个Github就是我们网络请求的接口:

public interface GitHub {    @GET("/repos/{owner}/{repo}/contributors")    Call<List<Contributor>> contributors(        @Path("owner") String owner,        @Path("repo") String repo);  }

在这里,retrofit使用了builder模式,我们可以在此设置请求的URL,ConverterFactory(此处用了Gson解析,当然你也可以自定义数据解析器,只要你的解析器继承 Converter.Factory就行),或者设置回调时的适配器。在retrofit中提供了三种CallAdapterFactoryGuavaCallAdapterFactoryJava8CallAdapterFactoryRxJavaCallAdapterFactory。比如要把response封装成rxjava的Observeble,然后对其进行流式操作:

Retrofit.Builder.addCallAdapterFactory(newRxJavaCallAdapterFactory().create());

然后我们点进去retrofit.create(GitHub.class)会发现:

 @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.  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();          @Override public Object invoke(Object proxy, Method method, Object... args)              throws Throwable {            if (method.getDeclaringClass() == Object.class) {              return method.invoke(this, args);            }            //对java8兼容            if (platform.isDefaultMethod(method)) {              return platform.invokeDefaultMethod(method, service, proxy, args);            }            //看缓存里面有没有这个method,要是有,就返回,要是没有,就生成一个,然后加入缓存            ServiceMethod serviceMethod = loadServiceMethod(method);            //生成一个OkHttpCall对象            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);            //调用OkHttp,然后根据okHttpCall返回rejava的Observe对象或者返回Call            return serviceMethod.callAdapter.adapt(okHttpCall);          }        });  }

这里的Platform 其实是检测retrofit所运行的平台,是java8还是android还是ios。这里主要是在builder的时候,如果没有设置适配器,那么retrofit就会通过运行时的不同平台,然后选择不同的CallAdapterFactory。从上面的代码可以看出,create 方法返回了一个动态代理对象,通过Github接口生成代理类,并将代理类的实现交给 InvocationHandler 作为具体的实现。这里使用动态代理的好处是简化复杂的网络请求和解析、封装ServiceMethod。

主要的网络请求类

OkHttpCall:这个类主要实现了Call<T>接口,主要的作用就是发送一个HTTP请求,retrofit默认的也是这个类,我们也可以根据不同的情况实现自己的Call类,这种设计很插件化。在OkHttpCall内部提供了异步和同步两种方法来发送请求,分别是同步的OkHttpCall.execute()和异步的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 {          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();        }      }    });  }

这里的call就是okhttp3.Call,在这里通过用call.enqueue(...)把请求交给okhttp的队列中,然后再通过异步回调切换到主线程,这里线程切换主要是通过前面的retrofit在build()的时候,Platform检测到运行环境在android的时候,就会跳到Android:

 static class Android extends Platform {    @Override public Executor defaultCallbackExecutor() {      return new MainThreadExecutor();    }    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {      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);      }    }  }

看到上面的MainThreadExecutor 就能看出来,在execute()的时候,retrofit获取了主线程的handler,然后在UI线程执行网络请求回调后的数据显示等操作。

网络请求流程总结

  • 首先,在Retrofitbuild的时候,我们假设设置了newRxJavaCallAdapterFactory().create(),还加上了addConverterFactory(GsonConverterFactory.create())
  • 在当我们调用github.contributors("square", "retrofit");的时候,其实是调用了动态代理的InvocationHandler,在InvocationHandler中,我们看到有一个ServiceMethod,这里用了缓存,缓存了之前调用过的网络请求的方法,loadServiceMethod(method)方法检测缓存里面有没有调用过这个method,要是有,就返回,要是没有,就生成一个(此时会解析contributors(),解析我们在contributors()上面加的Annotation等,以便后面封装成request),然后加入缓存。
  • 然后生成一个OkHttpCallserviceMethod.callAdapter.adapt(OkHttpCall),此时的callAdapter就是RxJavaCallAdapterFactory
  • InvocationHandler中的最后一行代码中, return serviceMethod.callAdapter.adapt(okHttpCall);此时调用了RxJavaCallAdapterFactory.adapt()方法,返回我们想要的对象,比如android里面默认的Call<>,或者我们这里设置了RxJavaCallAdapterFactory,所以返回的是Observable<>。
  • 当我们调用了rxjava的subscribe方法的时候(或者调用Call的enqueue方法) ,做了下面几件事:
    • 首先执行okHttpCall的execute()方法把网络请求交给okHttp,当完成请求后,会对网络请求的结果进行解析,在解析时,会调用serviceMethod.toResponse(catchingBody),这里会通过我们之前设置的GsonConverterFactory来解析返回的数据(比如通过GSON解析什么的),然后再生成一个Response类.
    • 再回调到ExecutorCallAdapterFactory(这个CallAdapterFactory是之前在retrofit的build()方法中通过Platform检测环境,然后设置的一个CallAdapterFactory),这个CallAdapterFactory的adapt()中生成了一个ExecutorCallbackCall对象,在这个ExecutorCallbackCallenqueue(CallBack)中,会调用MainThreadExecutorexecute()方法,此时就是之前说的利用handler切换到主线程。
    • 最后因为我们使用了rxjava,所以在这里会对返回的call对象进行了进一步封装,生成了我们需要的Observable<Response>,最后我们就可以在主线程中进行开心的rx的流式操作了!

0 0
原创粉丝点击