目录
1. 前言
2. 简介
3. 火热热的4个网络框架
4. 如何使用
5. 源码分析
6. 后记
1. 前言今年是2020年了,也是我正式入驻CSDN博客的第一年,说起来也凑巧,因为今年的黑天鹅事件导致我们不得不在家宅着,当然到2月中下旬很多企业都复工了,本人也一样进入了远程办公状态,其实本人挺懒的,写文章这种事情我其实是不怎么热衷的,主要还是因为在家宅久了觉得会不够充实,于是乎有时间去学习下当下流行的Android开发技术,想通过写博客的方式梳理下自己学到的知识点。好了,我就不废话了,直接进入真题吧,以下便是关于我学习Retrofit网络框架的总结。
2. 简介Retrofit2是基于OkHttp作了二次封装的网络请求框架,由Square公司开发的,现已流行好几年了,当然大家都知道Square公司是很有名气的,著名全家桶就有okhttp,retrofit,okio,picasso,leakcanary,javapoet等。某某要是问我,Retrofit2哪里好用,相比okhttp好在哪?那么我就只好这么回答了,它适用于后台Api遵循Restful API设计风格的场景,此外,最突出的地方就是对RxJava的完美支持,据博客资源记载,目前最流行的一套网络请求套装大概就是Retrofit+RxJava+Mvp了。还要再夸下它的功能是十分强大的,不仅支持同步和异步请求,还支持多种数据格式解析;简洁易使用,通过注解配置网络请求参数,并运用许多设计模式简化使用;可拓展性好,解耦性高。
3. 火热热的4个网络框架这里我就直接贴上这四个框架的github热度让大家参考一番,这个最有权威性。
https://github.com/square/retrofit
https://github.com/square/okhttp
https://github.com/google/volley
https://github.com/wyouflf/xUtils3
因为我学习android的时候只用到了OkHttp,最近才用到Retrofit,而Volley和XUtils等其他框架我还没用到过,以后有时间我再去仔细研究下了,所以我暂时只能传递(cv)网友的理解分析一下。
(1)Okhttp:OkHttp是Square公司开源的针对Java和Android程序,封装的一个高性能http请求库,它的职责跟HttpUrlConnection 是一样的,支持 spdy、http 2.0、websocket ,支持同步、异步,而且 OkHttp 又封装了线程池,封装了数据转换,封装了参数使用、错误处理等。该框架使用门槛不高,需要自己稍微封装一下便可方便使用。
(2)Retrofit:对OkHttp的二次封装,使用了大量的注解来简化代码,并且支持RxJava。该框架几乎没有缺点,唯独就是搭配RxJava使用起来会有一定的难度,学习成本高,期间会遇到不少的坑点需要使用者们多去研究下。
(3)Volley:据说很多小伙伴们都在用这套框架,网传其被封装的很好,并支持简单的图片加载,使用者几乎不用再对他进行二次封装了,唯独不好的地方就是不支持post大数据,不能下载文件,以及不适合上传文件。
(4)XUtils:这是我最近才接触到的一个框架,第一次发现它是在我同事负责的项目里有看到的,好像是国人写的,网传它不仅能支持基本的网络请求,还支持图片加载处理,以及数据储存等,缺点是会导致项目对该框架的依赖过重。
那么现在问题来了,到底该用哪套框架到我们的项目中去?我个人觉得还是得看团队的选择,以及实际的项目需求重点,取其所长,补齐所短,才能发挥起框架的最大价值。
4. 如何使用因为Retrofit使用了大量的注解来处理网络请求参数信息,熟悉其注解的含义自然会是重中之重了,这里我就cv一下Carson_Ho大神的图片资源(来自https://blog.csdn.net/carson_ho/article/details/73732076),大家要先了解下其中的注解名词,关于注解的具体含义可以参考下丨Fan的文章(来自https://www.jianshu.com/p/8e1b76b8939d),这样后面就会看的懂一些。
5. 源码分析5.1 UML类图(省略掉成员属性)
这里附上UML类图的作法链接:http://www.uml.org.cn/oobject/20111271.asp 以及 https://www.cnblogs.com/wanghuaijun/p/5421419.html
5.2 源码流程(1)之 创建Retrofit实例
相信各位老铁已经了解了Retrofit使用流程,如果还没了解,也没关系,可以先参考一下第四章节:4.如何使用。
好,根据上面Retrofit实例的创建过程,我先贴下源代码:
/** * Build a new {@link Retrofit}. *
* Calling {@link #baseUrl} is required before calling {@link #build()}. All other methods * are optional. */ public static final class Builder { private final Platform platform; private @Nullable okhttp3.Call.Factory callFactory; private @Nullable HttpUrl baseUrl; private final List converterFactories = new ArrayList(); private final List callAdapterFactories = new ArrayList(); private @Nullable Executor callbackExecutor; private boolean validateEagerly; Builder(Platform platform) { this.platform = platform; } public Builder() { this(Platform.get()); }
说明:
这里Builder类作为Retrofit的内部类,运用到了建造者模式,原理是交由Builder类创建一个一个小组件(这里包括添加baseUrl,请求适配器CallAdapter,数据转换器CallConverter,etc..),最后通过其build方法创建一个最终的目标对象,这是运用建造者模式的广泛作法,其他很多地方几乎都是这么个套用法。
其次,这里我们还看到了Platform类,通过它可以拿到Platform.Android实例,那有什么用呢?先贴下源码:
/** * Create the {@link Retrofit} instance using the configured values. *
* Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link * OkHttpClient} will be created and used. */ 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 callAdapterFactories = new ArrayList(this.callAdapterFactories); callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor)); // Make a defensive copy of the converters. List converterFactories = new ArrayList( 1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize()); // Add the built-in converter factory first. This prevents overriding its behavior but also // ensures correct behavior when using converters that consume all types. converterFactories.add(new BuiltInConverters()); converterFactories.addAll(this.converterFactories); converterFactories.addAll(platform.defaultConverterFactories()); return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); }
说明:根据注释和源码,我们可以知道:
1.如果之前没有添加okhttp3.Call.Factory的实现类实例的话,就会创建一个OkHttpClient实例,这里大多数情况下让它直接默认创建即可;
2.如果之前没有添加Executor,那么在Android平台会为我们创建一个MainThreadExecutor,这个类其实就是封装了一个主线程的Handler,其用法相信大家也能猜得出来,后面我再提及它;
3.固定添加1~2个请求适配器工厂DefaultCallAdapterFactory和CompletableFutureCallAdapterFactory(要求API24以上);
4.固定添加1~2个数据转换器工厂BuiltInConverters和OptionalConverterFactory(要求API24以上)。
5.完成Retrofit实例创建。
5.3 源码流程(2)之 创建网络请求接口
先上源代码:
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety. public T create(final Class 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(); private final Object[] emptyArgs = new Object[0]; @Override public @Nullable 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); } return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } }); }
说明:这里运用到了动态代理,即需要事先写好一个网络请求接口,这里假设传一个INetService,通过代码INetService iNetService = retrofit.create(INetService.class)即可创建网络请求接口实例,INetService接口代码示例如下:
public interface INetService { @GET("{subPath}") Call get(@Path("subPath") String subUrl, @QueryMap Map params); //post请求以表单形式传参 @FormUrlEncoded @POST("{subPath}") Call postForm(@Path("subPath") String subUrl, @FieldMap Map params); //post请求以Json形式传参 @POST("{subPath}") Call postJson(@Path("subPath") String subUrl, @Body Object params); @FormUrlEncoded @PUT("{subPath}") Call put(@Path("subPath") String subUrl, @FieldMap Map params); @DELETE("{subPath}") Call delete(@Path("subPath") String subUrl, @QueryMap Map params); @Streaming @GET("{subPath}") Call download(@Header("Range") String range, @Path("subPath") String subUrl, @QueryMap Map params); @Multipart @POST("{subPath}") Call upload(@Path("subPath") String subUrl, @Part List mapFile); }
5.4 源码流程(3)之 执行网络请求
说明:现在我们回过来注意下Retrofit类的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 = ServiceMethod.parseAnnotations(this, method); serviceMethodCache.put(method, result); } } return result; }
说明:这里运用了享元模式,之所以这么做,是为了不去反复的执行解析注解的操作,因为网络接口写好了,就不会在运行期间动态修改,另外就是某接口方法可能会执行多次,若每次都去解析其注解信息的话,就每次都会影响执行效率。
比如,我执行了INetService接口中的get方法,那么会走loadServiceMethod方法,如果是第一次,会先调用ServiceMethod.parseAnnotations(this, method)语句,即解析其方法注解,这里我先贴上源代码:
abstract class ServiceMethod { static ServiceMethod parseAnnotations(Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError(method, "Method return type must not include a type variable or wildcard: %s", returnType); } if (returnType == void.class) { throw methodError(method, "Service methods cannot return void."); } return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); } abstract @Nullable T invoke(Object[] args); }
说明:这里会依赖到RequestFactory类,再上其源码:
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) { return new Builder(retrofit, method).build(); }
Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; this.methodAnnotations = method.getAnnotations(); this.parameterTypes = method.getGenericParameterTypes(); this.parameterAnnotationsArray = method.getParameterAnnotations(); } RequestFactory build() { for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } if (httpMethod == null) { throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.)."); } if (!hasBody) { if (isMultipart) { throw methodError(method, "Multipart can only be specified on HTTP methods with request body (e.g., @POST)."); } if (isFormEncoded) { throw methodError(method, "FormUrlEncoded can only be specified on HTTP methods with " + "request body (e.g., @POST)."); } } int parameterCount = parameterAnnotationsArray.length; parameterHandlers = new ParameterHandler[parameterCount]; for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) { parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter); } if (relativeUrl == null && !gotUrl) { throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod); } if (!isFormEncoded && !isMultipart && !hasBody && gotBody) { throw methodError(method, "Non-body HTTP method cannot contain @Body."); } if (isFormEncoded && !gotField) { throw methodError(method, "Form-encoded method must contain at least one @Field."); } if (isMultipart && !gotPart) { throw methodError(method, "Multipart method must contain at least one @Part."); } return new RequestFactory(this); }
说明:第一个for循环是为了遍历解析INetService接口某方法所有注解,往后看,依赖到ParameterHandler类,咋一看类名就知道是用来处理方法参数的,事实上的确如此,ParameterHandler类里头有很多的内部继承者,比如ParameterHandler.Part类,它主要维护了一个数据解析引用(Converter),然后方法apply是为了把调用者传过来的参数值value封装到请求体Requestbody中,并且在这之前会通过Converter做数据解析的操作。
static final class Part extends ParameterHandler { private final Method method; private final int p; private final okhttp3.Headers headers; private final Converter converter; Part(Method method, int p, okhttp3.Headers headers, Converter converter) { this.method = method; this.p = p; this.headers = headers; this.converter = converter; } @Override void apply(RequestBuilder builder, @Nullable T value) { if (value == null) return; // Skip null values. RequestBody body; try { body = converter.convert(value); } catch (IOException e) { throw Utils.parameterError(method, p, "Unable to convert " + value + " to RequestBody", e); } builder.addPart(headers, body); } }
接下来我们来看下HttpServiceMethod类:
static HttpServiceMethod parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) { boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction; boolean continuationWantsResponse = false; boolean continuationBodyNullable = false; Annotation[] annotations = method.getAnnotations(); Type adapterType; if (isKotlinSuspendFunction) { Type[] parameterTypes = method.getGenericParameterTypes(); Type responseType = Utils.getParameterLowerBound(0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]); if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) { // Unwrap the actual body type from Response. responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType); continuationWantsResponse = true; } else { // TODO figure out if type is nullable or not // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class) // Find the entry for method // Determine if return type is nullable or not } adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType); annotations = SkipCallbackExecutorImpl.ensurePresent(annotations); } else { adapterType = method.getGenericReturnType(); } CallAdapter callAdapter = createCallAdapter(retrofit, method, adapterType, annotations); Type responseType = callAdapter.responseType(); if (responseType == okhttp3.Response.class) { throw methodError(method, "'" + getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?"); } if (responseType == Response.class) { throw methodError(method, "Response must include generic type (e.g., Response)"); } // TODO support Unit for Kotlin? if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) { throw methodError(method, "HEAD method must use Void as response type."); } Converter responseConverter = createResponseConverter(retrofit, method, responseType); okhttp3.Call.Factory callFactory = retrofit.callFactory; if (!isKotlinSuspendFunction) { return new CallAdapted(requestFactory, callFactory, responseConverter, callAdapter); } else if (continuationWantsResponse) { //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object. return (HttpServiceMethod) new SuspendForResponse(requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call>) callAdapter); } else { //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object. return (HttpServiceMethod) new SuspendForBody(requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call>) callAdapter, continuationBodyNullable); } }
说明:ServiceMethod类会调用HttpServiceMethod.parseAnnotations方法,该方法会根据网络请求接口方法的返回类型(比如:Call)来匹配合适的请求适配器CallAdapter,并根据返回类型里的泛型参数类型(比如:BasicResponse)来匹配合适的数据转换器CallConverter,最后返回一个CallAdapted实例。
经过以上一大波操作之后,终于ServiceMethod实例被创建好了,稍微总结一下,期间主要是解析或封装了网路请求接口中的请求头,请求参数信息,以及合适的请求适配器和数据转换器等。下面再回到这里:
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
说明:其实loadServiceMethod(Method method)方法做了几乎所有的准备工作,那么接下来的执行任务就交给了HttpServiceMethod类的invoke方法来进行,下面上代码:
@Override final @Nullable ReturnT invoke(Object[] args) { Call call = new OkHttpCall(requestFactory, args, callFactory, responseConverter); return adapt(call, args); }
说明:创建了OkHttpCall,并且这个OkHttpCall实现了Call接口,下面我们来看下这个类是做什么的。
final class OkHttpCall implements Call { private final RequestFactory requestFactory; private final Object[] args; private final okhttp3.Call.Factory callFactory; private final Converter responseConverter; private volatile boolean canceled; @GuardedBy("this") private @Nullable okhttp3.Call rawCall; @GuardedBy("this") // Either a RuntimeException, non-fatal Error, or IOException. private @Nullable Throwable creationFailure; @GuardedBy("this") private boolean executed; OkHttpCall(RequestFactory requestFactory, Object[] args, okhttp3.Call.Factory callFactory, Converter responseConverter) { this.requestFactory = requestFactory; this.args = args; this.callFactory = callFactory; this.responseConverter = responseConverter; }
说明:看到这里的时候,相信大家已经看到最后的原生rawCall引用了,并且还维护了一个OkHttpClient实例,等等,OkHttpClient实例?对的,就是那个callFactory引用啦,OkHttpClient实例是在构建Retrofit实例的时候被默认创建好的,只不过经过好几轮的传参最后回到了这里才被真正派上用场了。下面再看下:
private okhttp3.Call createRawCall() throws IOException { okhttp3.Call call = callFactory.newCall(requestFactory.create(args)); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; }
@Override public void enqueue(final Callback 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) { throwIfFatal(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) { Response response; try { response = parseResponse(rawResponse); } catch (Throwable e) { throwIfFatal(e); callFailure(e); return; } try { callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { throwIfFatal(t); t.printStackTrace(); // TODO this is not great } } @Override public void onFailure(okhttp3.Call call, IOException e) { callFailure(e); } private void callFailure(Throwable e) { try { callback.onFailure(OkHttpCall.this, e); } catch (Throwable t) { throwIfFatal(t); t.printStackTrace(); // TODO this is not great } } }); }
说明:到这里相信大家已经知道,这里便是我们封装OkHttp网络请求的熟悉代码了。先得到原生rawCall,这里用到了RequestFactory类,根据newCall方法我们就知道RequestFactory就是用来创建Request请求对象的。我先贴上源代码:
final class RequestFactory { static RequestFactory parseAnnotations(Retrofit retrofit, Method method) { return new Builder(retrofit, method).build(); } private final Method method; private final HttpUrl baseUrl; final String httpMethod; private final @Nullable String relativeUrl; private final @Nullable Headers headers; private final @Nullable MediaType contentType; private final boolean hasBody; private final boolean isFormEncoded; private final boolean isMultipart; private final ParameterHandler[] parameterHandlers; final boolean isKotlinSuspendFunction; RequestFactory(Builder builder) { method = builder.method; baseUrl = builder.retrofit.baseUrl; httpMethod = builder.httpMethod; relativeUrl = builder.relativeUrl; headers = builder.headers; contentType = builder.contentType; hasBody = builder.hasBody; isFormEncoded = builder.isFormEncoded; isMultipart = builder.isMultipart; parameterHandlers = builder.parameterHandlers; isKotlinSuspendFunction = builder.isKotlinSuspendFunction; } okhttp3.Request create(Object[] args) throws IOException { @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types. ParameterHandler[] handlers = (ParameterHandler[]) parameterHandlers; int argumentCount = args.length; if (argumentCount != handlers.length) { throw new IllegalArgumentException("Argument count (" + argumentCount + ") doesn't match expected count (" + handlers.length + ")"); } RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody, isFormEncoded, isMultipart); if (isKotlinSuspendFunction) { // The Continuation is the last parameter and the handlers array contains null at that index. argumentCount--; } List argumentList = new ArrayList(argumentCount); for (int p = 0; p < argumentCount; p++) { argumentList.add(args[p]); handlers[p].apply(requestBuilder, args[p]); } return requestBuilder.get() .tag(Invocation.class, new Invocation(method, argumentList)) .build(); }
说明:这里别看RequestFactory维护了大量的引用,其实唯一做了一件最有意义的事情就是创建RequestBuilder类对象,下面我们来看下RequestBuilder类:
Request.Builder get() { HttpUrl url; HttpUrl.Builder urlBuilder = this.urlBuilder; if (urlBuilder != null) { url = urlBuilder.build(); } else { // No query parameters triggered builder creation, just combine the relative URL and base URL. //noinspection ConstantConditions Non-null if urlBuilder is null. url = baseUrl.resolve(relativeUrl); if (url == null) { throw new IllegalArgumentException( "Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl); } } RequestBody body = this.body; if (body == null) { // Try to pull from one of the builders. if (formBuilder != null) { body = formBuilder.build(); } else if (multipartBuilder != null) { body = multipartBuilder.build(); } else if (hasBody) { // Body is absent, make an empty body. body = RequestBody.create(null, new byte[0]); } } MediaType contentType = this.contentType; if (contentType != null) { if (body != null) { body = new ContentTypeOverridingRequestBody(body, contentType); } else { headersBuilder.add("Content-Type", contentType.toString()); } } return requestBuilder .url(url) .headers(headersBuilder.build()) .method(method, body); }
说明:是否对这里的代码灰常的熟悉,下面我贴下OkHttp的常用代码:
OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象。 MediaType JSON = MediaType.parse("application/json; charset=utf-8");//数据类型为json格式, String jsonStr = "{\"username\":\"lisi\",\"nickname\":\"李四\"}";//json数据. RequestBody body = RequestBody.create(JSON, josnStr); Request request = new Request.Builder() .url("http://www.baidu.com") .post(body) .build(); client.newCall(request).enqueue(new Callback() { ....});
说明:很明显RequestBuilder根据不同的请求方式来实例化一个合适的请求体RequestBody,这个请求体可能是FormBody,RequestBody,MultipartBody等,最后再以Request.Builder对象返回。
@Override final @Nullable ReturnT invoke(Object[] args) { Call call = new OkHttpCall(requestFactory, args, callFactory, responseConverter); return adapt(call, args); } protected abstract @Nullable ReturnT adapt(Call call, Object[] args); static final class CallAdapted extends HttpServiceMethod { private final CallAdapter callAdapter; CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory, Converter responseConverter, CallAdapter callAdapter) { super(requestFactory, callFactory, responseConverter); this.callAdapter = callAdapter; } @Override protected ReturnT adapt(Call call, Object[] args) { return callAdapter.adapt(call); } }
说明:通过invoke方法拿到我们的Call接口,通过CallAdapted类代理了一个CallAdapter接口引用,这里默认就是我们之前匹配好的合适的请求适配器,如果要问它在哪里?它在DefaultCallAdapterFactory工厂类里匿名内部类实现了。贴下源码:
final class DefaultCallAdapterFactory extends CallAdapter.Factory { private final @Nullable Executor callbackExecutor; DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) { this.callbackExecutor = callbackExecutor; } @Override public @Nullable CallAdapter get( Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != Call.class) { return null; } if (!(returnType instanceof ParameterizedType)) { throw new IllegalArgumentException( "Call return type must be parameterized as Call or Call"); } final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType); final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null : callbackExecutor; return new CallAdapter<Object, Call>() { @Override public Type responseType() { return responseType; } @Override public Call adapt(Call call) { return executor == null ? call : new ExecutorCallbackCall(executor, call); } }; }
static final class ExecutorCallbackCall implements Call { final Executor callbackExecutor; final Call delegate; ExecutorCallbackCall(Executor callbackExecutor, Call delegate) { this.callbackExecutor = callbackExecutor; this.delegate = delegate; } @Override public void enqueue(final Callback callback) { checkNotNull(callback, "callback == null"); delegate.enqueue(new Callback() { @Override public void onResponse(Call call, final Response 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 call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallbackCall.this, t); } }); } }); }
说明:这里ExecutorCallbackCall其实是个代理类,它代理了Call对象,以及维护了一个Executor引用,这个Executor其实就是那个MainThreadExecutor。调用者最后拿到的对象就是ExecutorCallbackCall,通过它走enqueue方法,再通过MainThreadExecutor实现了在主线程回调接口方法。over~
6. 后记写这篇文章花了我几天时间吧,文章概括的内容是肯定不完善的,我后续还会继续更新的,亲爱的老铁们若发现文章有误的地方可以在下方评论留言,或者私聊我一下也行的,我好及时更正,以免误导新手,希望能和大家在Android领域里共同进步。
参考链接:
https://blog.csdn.net/carson_ho/article/details/73732076
https://www.jianshu.com/p/8e1b76b8939d
https://blog.csdn.net/lmj623565791/article/details/51304204
https://blog.csdn.net/fightingXia/article/details/70947701
源码下载:
https://github.com/ddgFh/RetrofitDemo/tree/master
作者:IronMan_23