retrofit2源码分析
来源:互联网 发布:网络直播学校 编辑:程序博客网 时间:2024/06/06 00:53
如果对retrofit使用不太了解的可以去网上查一些资料,本篇就直接对源码进行分析了。
一、首先你需要RestfulApi 类,里面声明了咱们的请求
public interface RestfulApi { // 获取时间戳 @POST("app.do?") Call<T> getTime(@Query("pattern") String pattern);}
然后封装Retrofit
public class HttpClient { private RestfulApi apiService; private OkHttpClient okHttpClient; public HttpClient(Context context) { okHttpClient = genericClient(); Retrofit retrofit = new Retrofit.Builder().baseUrl(AppEnvConstants.http_ip) .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient) .build(); apiService = retrofit.create(RestfulApi.class); } // 创建OkHttpClient实例 private OkHttpClient genericClient() { return new OkHttpClient.Builder(). addInterceptor(new HttpInterceptor()) .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build(); }}
然后调用异步接口就是
Call<T> call = apiService.getTime(pattern);call.enqueue(callback);
二、下边针对retrofit2进行源码分析
// 创建OkHttpClient实例 private OkHttpClient genericClient() { return new OkHttpClient.Builder(). addInterceptor(new HttpInterceptor()) .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build(); }
这一段代码很明显是对OkHttp中OkHttpClient的初始化,对OkHttp不了解可以看下
OkHttp3源码分析
Retrofit retrofit = new Retrofit.Builder().baseUrl(AppEnvConstants.http_ip) .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient) .build();
这一段代码是对Retrofit的初始化
addConverterFactory(GsonConverterFactory.create())//对返回的数据支持json格式解析
client(okHttpClient)//设置okhttp3.Call.Factory callFactory = okHttpClient
最主要的就是下面这段代码
apiService = retrofit.create(RestfulApi.class);
查看源码
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) {//反射获取到的类全名称 return method.invoke(this, args); } if (platform.isDefaultMethod(method)) {//Android/ios返回false,java8返回true return platform.invokeDefaultMethod(method, service, proxy, args); } //组装ServiceMethod,里面有缓存,一样的方法只会执行一次,这个很大程度上优化了性能,因为反射是会消耗性能的 ServiceMethod serviceMethod = loadServiceMethod(method); //传入的serviceMethod和参数 OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); }
发现上面是典型的Java动态代理
看上面的注释,Android中一定会走到下面,直接分析下面重要代码
ServiceMethod serviceMethod = loadServiceMethod(method);
ServiceMethod loadServiceMethod(Method method) { ServiceMethod result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method);//从缓存中获取serviceMethod if (result == null) { result = new ServiceMethod.Builder(this, method).build(); serviceMethodCache.put(method, result); } } return result; }
由于动态代理是用的反射的原理,然而所有的反射都有性能消耗,这里对method进行了缓存,每个方法只会运行一次
private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
final修饰,引用地址不可变,这里用了LinkedHashMap表示不是很理解,LinkedHashMap底层是链表实现的,哪位朋友知道评论一下
//TODO
ServiceMethod里面的代码暂缓,等下再分析
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
看一下OkHttpCall的构造器
OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) { this.serviceMethod = serviceMethod; this.args = args; }
只是把刚声明的ServiceMethod和args参数传过去
serviceMethod.callAdapter.adapt(okHttpCall);
三、分析问题
1、serviceMethod.callAdapter是什么?
2、serviceMethod.callAdapter.adapt(okHttpCall)是什么?
先分析一下第一个问题
首先看ServiceMethod的build()里
public ServiceMethod build() { callAdapter = createCallAdapter()
private CallAdapter<?> 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 { return retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(e, "Unable to create call adapter for %s", returnType); } }
跑到了Retrofit类里
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<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);//ExecutorCallAdapterFactory 执行 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()); }
最后走到了nextCallAdapter里,然后看只是从adapterFactories里取数据,看一下adapterFactories是什么
看一下Retrofit的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(); } 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); } }
重点看一下
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));
看一下Android的Platform
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); } } }
callbackExecutor = platform.defaultCallbackExecutor() = new MainThreadExecutor();
由于MainThreadExecutor里的handler创建的Looper是主线程里的,so handler也是主线程(UI线程)里的,对Android的异步消息机制不了解的可以看下异步消息机制
看到没最后把UI线程赋值给了callbackExecutor
adapterFactories最后add的是ExecutorCallAdapterFactory
然后再回过头来
CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);//等同于CallAdapter<?> adapter = ExecutorCallAdapterFactory.get(returnType, annotations, this);
看一下ExecutorCallAdapterFactory类
final class ExecutorCallAdapterFactory extends CallAdapter.Factory { final Executor callbackExecutor;//MainThreadExecutor 主线程 ExecutorCallAdapterFactory(Executor callbackExecutor) { this.callbackExecutor = callbackExecutor; } @Override public CallAdapter<Call<?>> 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 new ExecutorCallbackCall<>(callbackExecutor, call); } }; } 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;//okhttpCall } @Override public void enqueue(final Callback<T> callback) { if (callback == null) throw new NullPointerException("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(); } }}
回过头来看一下问题
1、serviceMethod.callAdapter是什么?
2、serviceMethod.callAdapter.adapt(okHttpCall)是什么?
答案:
serviceMethod.callAdapter = ExecutorCallAdapterFactory.get(returnType, annotations, this);
callbackExecutor = MainThreadExecutor,这个是retrofit里传进来的
serviceMethod.callAdapter.adapt(okHttpCall) = ExecutorCallAdapterFactory.get(returnType, annotations, this).adapt(okHttpCall) = new ExecutorCallbackCall<>(callbackExecutor, okHttpCall) = new ExecutorCallbackCall<>(MainThreadExecutor, okHttpCall)
回过头来看一下我们业务层写的请求
Call<T> call = apiService.getTime(pattern);call.enqueue(listener);
call = serviceMethod.callAdapter.adapt(okHttpCall) = new ExecutorCallbackCall<>(MainThreadExecutor, okHttpCall);
call.enqueue(callback) = ExecutorCallbackCall.enqueue(callback)
最后走到了OkHttpCall里,各位看官请看
delegate = OkHttpCall.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); } }); } });
搞一段落,终于搞清楚了,最后代码会走到OkHttpCall.enqueue();
分析一下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(); } } }); }
private okhttp3.Call createRawCall() throws IOException { Request request = serviceMethod.toRequest(args); okhttp3.Call call = serviceMethod.callFactory.newCall(request);//serviceMethod.callFactory是okhttpClient if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; }
ServiceMethod的builder
ServiceMethod(Builder<T> builder) { this.callFactory = builder.retrofit.callFactory();
Retrofit里的
public Builder client(OkHttpClient client) { return callFactory(checkNotNull(client, "client == null")); } /** * Specify a custom call factory for creating {@link Call} instances. * <p> * Note: Calling {@link #client} automatically sets this value. */ public Builder callFactory(okhttp3.Call.Factory factory) { this.callFactory = checkNotNull(factory, "factory == null"); return this; }
这里面的逻辑其实就是走到了OkHttp里的RealCall.enqueue,然后再解析,回调。
对OkHttp不是很了解可以看下OkHttp源码分析
对源码逻辑明白了,但是想一想设计者为什么要这样设计retrofit,你会学到的更多。
retrofit的设计模式这篇文章写的特别好。
盗用一下图
真的是很美妙啊啊……..
- Retrofit2.0源码分析
- Retrofit2源码分析
- Retrofit2 源码分析
- Retrofit2 源码分析
- Retrofit2.0源码分析
- Retrofit2 源码分析
- retrofit2源码分析
- Retrofit2源码分析
- retrofit2源码分析
- retrofit2.0源码分析
- Retrofit2实现源码分析
- Retrofit2源码分析
- Retrofit2 源码分析(清晰版)
- Retrofit2源码初探
- Retrofit2源码解读
- Retrofit2源码解析
- Retrofit2 源码解析
- Retrofit2.0源码解析
- Xcode 上模拟器显示大小的调整
- 喇叭-扬声器的功率
- notify()和notifyAll()主要区别
- KVO健值监听(观察者)
- CSS3用transition实现边框动画效果
- retrofit2源码分析
- 中国互联网惊呆老外?微信大数据揭露“无现金”真相
- Linux 下mysql 启动失败 Multiple MySQL running but PID file could not be found (1761 1448)[失败]
- spring事务的传播行为和隔离级别
- Struts2_访问或添加request等属性
- ajax中的一些参数的含义及用法
- 国外的一些ASP.NET+C#开源CMS
- js数组去除重复数据
- 如何手动更新 Laravel Homestead