retrofit源码解析

what is retrofit

A type-safe HTTP client for Android and Java
适用于java8 和android平台。使用okio进行网络请求。

how to use retrofit

//first define an interface discribe the url and param
public interface GitHubService {
  @GET("users/{user}/repos")
  Call> listRepos(@Path("user") String user);
}

public class RetrofitSample {
    public void testRetrofit() {
         //定义要访问的url路径
         Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .addConverterFactory(GsonConverterFactory.create())//使用不同的json解析器, retrofit只对body进行处理。
            .build();

         GitHubService service = retrofit.create(GitHubService.class);
         
         Call> repos = service.listRepos("octocat");
         // 请求数据,并且处理response 
        repos.enqueue(new Callback>() { 
            @Override 
            public void onResponse(Response> author) {
                 Log.d()
            } 
            @Override 
            public void onFailure(Throwable t) {
         } });
         //the code above will request url: https://api.github.com/users/octocat/repos
        // 返回的值封装成为List形式的数值。
    }
}

更多用法参考:你真的会用retrofit 这里面有更详细的使用介绍。

how does it work

首先,针对retrofit初始化的代码:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

new Retrofit.Build() 会调用Build(Platform.get())方法,根据是否有"android.os.Build" 来判断是否是android平台, 如果是android平台, 则创建一个主线程执行器, 这里我们可以知道,retrofit需要将任务(例如请求数据完毕,将数据返回到主线程)抛到主线程执行,直接调用MainThreadExcutor.excute(new Runnable(){})就可以了
事实上如果希望使用rxjava或者其他的类型,这里可以通过addAdapterFacotry()添加rxjava的adapter
同时还会添加一个默认的adapter, 对于android,默认的adapter就是ExecutorCallAdapterFactory,

static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }

除了这些信息,其他的信息通过Builder模式设置即可, 在调用Builder.build()的时候会判断使用哪种客户端(默认Okhttpclient), 哪种线程执行器(android 默认就是上面的MainThreadExecutor执行器), body转换器(没有设置内容转换器 则使用内建转换器), 然后生成了一个Retrofit代码。

对于GitHubService service = retrofit.create(GitHubService.class);
进入到create()内部查看,可以看到其主要实现是通过jdk的动态代理对最开始的GithubApiService做拦截处理。

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, @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);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod serviceMethod =
                (ServiceMethod) loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
 
 

在invoke方法内部, 主要是拦截GithubApiService已经注解的方法, 解析方法对应的参数,结合传递进来的参数,调用loadservicemethod生成一个serviceMethod实例,该实例保存了要发送请求的所有信息,并将serviceMethod以及参数一起传给OkHttpCall 生成一个实例,并包装成一个ExecutorCallAdaptFacoty(android)的实例。
ServiceMethod.Builder.build()方法先

通过serviceMethod.toRequest 可以将一个servicemethod转换成okhttp所需要的Request(),

最后再看调用Call.enque时,发生了什么事情

repos.enqueue(new Callback>() { 
            @Override 
            public void onResponse(Response> author) {
                 Log.d()
            } 
            @Override 
            public void onFailure(Throwable t) {
         } });

这里的repos实际是ExecutorCallAdaptFacoty的实例,查看里面的enque方法,实际调用的是OkHttpCall()的enque方法,并监听回调。而OkHttpCall()的方法实际最后调用的是okhttp3.Call的enque和execute()方法。

public Converter responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    if (type == ResponseBody.class) {
      return Utils.isAnnotationPresent(annotations, Streaming.class)
          ? StreamingResponseBodyConverter.INSTANCE
          : BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    return null;
  }

在okhttp处理完成后, 在将okhttp返回的数据进行处理时,会调用serviceMethod的toRsponse方法, 而responseconvert 的生成又是根据最开始设置retrofit的值来判断的,默认的类型有 StreamingResponseBodyConverter和BufferingResponseConverter, 实际是根据不同的返回值以及注解类型来做特别处理的。

总结

Retrofit实际是对okhttp的一层封装,通过注解的方式描述了一个http请求需要的信息,简化了okhttp的使用,对于返回数据的解析,使用了默认的Converter, 用户也可以使用其他的converter,例如gson convert等,也可以定义自己的converter。
Retrofit的代码主要是设计模式很牛逼,这里贴一张用户stay的模式图:

retrofit源码解析_第1张图片
Retrofit 里面涉及到的设计模式

refs:
Retrofit2

你可能感兴趣的:(retrofit源码解析)