retrofit2源码分析
来源:互联网 发布:南宁三中教师待遇知乎 编辑:程序博客网 时间:2024/06/01 23:02
先从Retrofit的使用开始介绍。一个简单的使用例子如下:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://172.18.157.142:8080") //.addConverterFactory(GsonConverterFactory.create()) .build(); TestApi testApi = retrofit.create(TestApi.class); Map<String,String> p = new HashMap<>(); p.put("key","123"); Call<ResponseBody> userCall = testApi.getTestResult("/user/nothing",p); userCall.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { System.out.println("================onFailure"); } });
okhttp使用例子:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
下面看他们是如何联系的(retrofit是基于okhttp3封装的)
TestApi的源码入下:
interface TestApi { @GET("{path}") Call<ResponseBody> getTestResult(@Path("path") String path, @QueryMap(encoded = true)Map<String,String> options);}
Retrofit的使用步骤还是比较麻烦的,主要有如下步骤:
1 创建一个Retrofit实例
2 根据具体的网络请求,创建一个接口,此接口的方法主要用于传入url和参数。
3 根据第二步创建的接口,获取一个Call。
4 调用Call的异步方法enqueue获取返回数据。
下面就从源码的角度详细分析Retrofit的原理。
先从第一步的build()方法开始,build()方法源码如下:
public Retrofit build() { if (baseUrl == null) { throw new IllegalStateException("Base URL required."); } okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient();//默认的Factory,可配置 } 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> adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // Make a defensive copy of the converters. List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories); return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); }
接下来看Retrofit的create()方法,源码如下:
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 the method is a method from Object then defer to normal invocation. if (method.getDeclaringClass() == Object.class) {//Object的相关方法不能被代理 return method.invoke(this, args); } if (platform.isDefaultMethod(method)) {//可以不用管,java里面用到,android平台默认为false return platform.invokeDefaultMethod(method, service, proxy, args); } ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);//获取ServiceMethod OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);//创建OkHttpCall return serviceMethod.callAdapter.adapt(okHttpCall);//动态代理的拦截执行 } }); }
create()方法返回了一个动态代理,从create()方法也可以看出,其参数service必须是一个接口,这个是动态代理的机制决定,有关动态代理相关知识,请自行百度。
Method的getDeclaringClass()方法返回Method定义所在的类。
动态代理最后调用了ServiceMethod的CallAdapter的adapt()方法。
ServiceMethod的CallAdapter是怎么初始化的呢?还需要从loadServiceMethod()这个方法说起。loadServiceMethod()源码如下:
ServiceMethod<?, ?> loadServiceMethod(Method method) { ServiceMethod<?, ?> result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = new ServiceMethod.Builder<>(this, method).build();//如果result中没有满足需求的ServiceMethod,就创建一个 serviceMethodCache.put(method, result); } } return result; }
ServiceMethod.Builder的build()方法源码如下:
public ServiceMethod build() { callAdapter = createCallAdapter();//创建CallAdapter …... return new ServiceMethod<>(this); }
createCallAdapter()方法源码如下:
private CallAdapter<T, R> createCallAdapter() { Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError( "Method return type must not include a type variable or wildcard: %s", returnType); } if (returnType == void.class) { throw methodError("Service methods cannot return void."); } Annotation[] annotations = method.getAnnotations(); try { //noinspection unchecked return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);//从Retrofit中获取。 } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(e, "Unable to create call adapter for %s", returnType); } }
Retrofit的callAdapter()源码如下:
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { return nextCallAdapter(null, returnType, annotations); } public CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { checkNotNull(returnType, "returnType == null"); checkNotNull(annotations, "annotations == null"); int start = adapterFactories.indexOf(skipPast) + 1; for (int i = start, count = adapterFactories.size(); i < count; i++) { //从链表中拿出一个CallAdapter.Factory,调用其get()方法,如果不为空,则返回。 CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this); if (adapter != null) { return adapter; } } StringBuilder builder = new StringBuilder("Could not locate call adapter for ") .append(returnType) .append(".\n"); if (skipPast != null) { builder.append(" Skipped:"); for (int i = 0; i < start; i++) { builder.append("\n * ").append(adapterFactories.get(i).getClass().getName()); } builder.append('\n'); } builder.append(" Tried:"); for (int i = start, count = adapterFactories.size(); i < count; i++) { builder.append("\n * ").append(adapterFactories.get(i).getClass().getName()); } throw new IllegalArgumentException(builder.toString()); }
adapterFactories.get()获取的CallAdapter.Factory其实就是Retrofit的Build在调用build()方法的时候设置的。先看Platform的源码:
static class Android extends Platform { @Override public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); } @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) { return new ExecutorCallAdapterFactory(callbackExecutor);//Retrofit使用的就是这个Factory } static class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } } }
所以adapterFactories.get()获取的就是ExecutorCallAdapterFactory。ExecutorCallAdapterFactory的get()方法源码如下:
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<Object, Call<?>>() { @Override public Type responseType() { return responseType; } @Override public Call<Object> adapt(Call<Object> call) { return new ExecutorCallbackCall<>(callbackExecutor, call); } }; }
先看if里面的判断条件,returnType的获取方式为:
method.getGenericReturnType()
Method的getGenericReturnType()返回的就是Method的返回值类型,比如:void,int,String等。而在这里代表的是文章开头描述的第二步中的接口中的方法返回值。如果不是Call的话,if会返回false,否则返回一个CallAdapter。
CallAdapter的adapt()方法返回的是一个ExecutorCallbackCall的实例。
也就是说Retrofit的create()方法的动态代理最终返回了一个ExecutorCallbackCall实例。
对应到开头的例子中,也就是
TestApi testApi = retrofit.create(TestApi.class);//获取的是一个代理类,而不是new出来的。 Call<ResponseBody> userCall = testApi.getTestResult("/user/renyiguang",p);//获取到的是ExecutorCallbackCall的实例。
所以在调用userCall.enqueue()方法时,其实是调用的ExecutorCallbackCall的enqueue()方法。ExecutorCallbackCall源码如下:
static final class ExecutorCallbackCall<T> implements Call<T> { final Executor callbackExecutor; final Call<T> delegate; ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) { this.callbackExecutor = callbackExecutor; this.delegate = delegate; } @Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); delegate.enqueue(new Callback<T>() { @Override public void onResponse(Call<T> call, final Response<T> response) { callbackExecutor.execute(new Runnable() { @Override public void run() { if (delegate.isCanceled()) { // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation. callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled")); } else { callback.onResponse(ExecutorCallbackCall.this, response); } } }); } @Override public void onFailure(Call<T> call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallbackCall.this, t); } }); } }); } @Override public boolean isExecuted() { return delegate.isExecuted(); } @Override public Response<T> execute() throws IOException { return delegate.execute(); } @Override public void cancel() { delegate.cancel(); } @Override public boolean isCanceled() { return delegate.isCanceled(); } @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone. @Override public Call<T> clone() { return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone()); } @Override public Request request() { return delegate.request(); } }
ExecutorCallbackCall其实是个代理类,其方法都是调用的delegate的相应方法。delegate是什么呢?是CallAdapter调用adapt()传入的参数。CallAdapter的adapt()是何时调用的呢?还是在Retrofit的create()中,传入的是OkHttpCall。
那么就看一下OkHttpCall的enqueue()方法,其源码如下:
@Override public void enqueue(final Callback<T> callback) { checkNotNull(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 { 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(); } } }); }
这个方法可以说是retrofit真正的入口方法。先来看一下createRawCall()这个方法。
private okhttp3.Call createRawCall() throws IOException { Request request = serviceMethod.toRequest(args);//根据输入参数返回Request。这是OkHttp的Request okhttp3.Call call = serviceMethod.callFactory.newCall(request);//根据request,返回call,这是OkHttp的call。 if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; }
ServiceMethod的toRequest()方法实现如下:
Request toRequest(Object... args) throws IOException { RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody, isFormEncoded, isMultipart); @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types. ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers; int argumentCount = args != null ? args.length : 0; if (argumentCount != handlers.length) { throw new IllegalArgumentException("Argument count (" + argumentCount + ") doesn't match expected count (" + handlers.length + ")"); } for (int p = 0; p < argumentCount; p++) { handlers[p].apply(requestBuilder, args[p]);//这里是参数参数配置的核心,具体细节下一节会专门分析 } return requestBuilder.build(); }
当拿到Okhttp的Request之后就是Okhttp的事情了。
- Retrofit2.0源码分析
- Retrofit2源码分析
- Retrofit2 源码分析
- Retrofit2 源码分析
- Retrofit2.0源码分析
- Retrofit2 源码分析
- retrofit2源码分析
- Retrofit2源码分析
- retrofit2源码分析
- retrofit2.0源码分析
- Retrofit2实现源码分析
- Retrofit2源码分析
- Retrofit2 源码分析(清晰版)
- Retrofit2源码初探
- Retrofit2源码解读
- Retrofit2源码解析
- Retrofit2 源码解析
- Retrofit2.0源码解析
- PLSQL Developer11远程连接oracle11G(一)
- 浅析Spring事务传播行为和隔离级别
- utf8mb4与utf8的区别
- AJAX问题之XMLHttpRequest status = 0
- cin输入操作的一些细节
- retrofit2源码分析
- selenium自动化测试资源整理(含所有版本chrome、chromedriver、firefox下载链接)
- 在js中 String 转json
- 导数与梯度、矩阵运算性质、科学计算库numpy
- com.test.mysql.entities.Clazz cannot be cast to java.io.Serializable
- C#接口的作用
- 六、自定义MVC
- doget()与dopost()的区别
- TabLayout使用详解