目录介绍
- 1.首先回顾Retrofit简单使用方法
- 2.Retrofit的创建流程源码分析
- 2.1 Retrofit对象调用Builder()源码解析
- 2.2 Retrofit对象调用baseUrl(url)源码解析
- 2.3 addConverterFactory(Converter.Factory factory)源码分析
- 2.4 addCallAdapterFactory(RxJava2CallAdapterFactory.create())源码分析
- 2.5 client(okHttpClient)源码分析
- 2.6 Retrofit对象调用build()源码解析
- 3.创建ServiceMethod流程源码分析
- 3.1 首先看看请求网络代码过程
- 3.2 分析create(final Class<T> service)源码
- 3.3 serviceMethod对象的创建过程
- 4.注解的解析
- 4.1 callAdapter的创建源码分析
- 4.2 responseConverter的创建源码分析
- 5.OkHttpCall的创建源码分析
- 5.1 new OkHttpCall<>(serviceMethod, args)源码分析
- 6.OkHttpCall的网络请求
- 6.1 OkHttpCall.execute()同步请求
- 6.2 OkHttpCall.enqueue()异步请求
- 6.3 parseResponse解析网络数据源码解析
好消息
- 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计47篇[近20万字],转载请注明出处,谢谢!
- 链接地址:https://github.com/yangchong211/YCBlogs
- 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!
- 关于Retrofit的使用,可以参考这篇文章:https://www.jianshu.com/p/989c46a858a4
0.思考问题,针对以下问题,看了这篇博客,应该有了初步的认识
1.首先回顾Retrofit简单使用方法
- Api接口
public interface DouBookApi {
- Model类
public class DouBookModel {private static DouBookModel bookModel; private DouBookApi mApiService; public DouBookModel(Context context) { mApiService = RetrofitWrapper .getInstance(ConstantALiYunApi.API_DOUBAN)
- 抽取类
public class RetrofitWrapper {private static RetrofitWrapper instance; private Retrofit mRetrofit; public RetrofitWrapper(String url) { OkHttpClient.Builder builder = new OkHttpClient.Builder();
- 使用
DouBookModel model = DouBookModel.getInstance(activity);
model.getHotMovie(mType,start,count).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<DouBookBean>() {@Overridepublic void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(DouBookBean bookBean) { } });
- 针对Retrofit,需要注意
- Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装。看下图所示,摘自网络

2.Retrofit的创建流程源码分析
- Retrofit实例是使用建造者模式通过Builder类进行创建的。Builder模式的优势:将一个复杂对象的构建与表示分离,使得用户在不知道对象的创建细节情况下就可以直接创建复杂的对象。
- 针对builder设计模式,可以参考我的这篇博客:https://blog.csdn.net/m0_37700275/article/details/78298505
- 关于使用builder模式写代码的案例,可以参考我的弹窗封装lib:https://github.com/yangchong211/YCDialog
2.1 Retrofit对象调用Builder()源码解析
2.2 Retrofit对象调用baseUrl(url)源码解析
- 都知道这个方法主要是设置baseUrl。源码如下所示
- 首先先对baseUrl进行非空判断。然后再解析baseUrl,如果解析的httpUrl为null,则会抛出IllegalArgumentException非法参数异常。那么思考一下,什么情况下解析baseUrl会导致解析内容httpUrl为null呢?
public Builder baseUrl(String baseUrl) {checkNotNull(baseUrl, "baseUrl == null")
- HttpUrl是如何解析url,对url有什么条件,来看一下parse方法源码
- 可以看到url必须是以http或者https才可以。如果随便写一个url,则会出问题
public static @Nullable HttpUrl parse(String url) { Builder builder = new Builder(); Builder.ParseResult result = builder.parse(null, url); return result == Builder.ParseResult.SUCCESS ? builder.build() : null; } ParseResult parse(@Nullable HttpUrl base, String input) { int pos = skipLeadingAsciiWhitespace(input, 0, input.length()); int limit = skipTrailingAsciiWhitespace(input, pos, input.length());
- 思考一下,传递的url为什么是String BASE_URL = "http://beta.goldenalpha.com.cn/"这个格式呢?接着看看baseUrl(httpUrl)源码
- 可以看到这里的url地址必须是以/结尾。所以如果是没有加上/,则会出现异常
public Builder baseUrl(HttpUrl baseUrl) {checkNotNull(baseUrl, "baseUrl == null");List<String> pathSegments = baseUrl.pathSegments();if (!"".equals(pathSegments.get(pathSegments.size() - 1))) { throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl); } this.baseUrl = baseUrl; return this; }
- 其实个人感觉这块工作并不难,只要有点英文基础的,就可以完全看的明白。接着往下分析,如果想了解更多,欢迎看我的博客汇总:https://github.com/yangchong211/YCBlogs
2.3 addConverterFactory(Converter.Factory factory)源码分析
- 在创建的时候会调用addConverterFactory(GsonConverterFactory.create(JsonUtils.getJson()))添加Gson转换器
- 这个方法主要是添加用于对象序列化和反序列化的转换器工厂
- 将上面创建的GsonConverterFactory放入到 converterFactories数组
.addConverterFactory(GsonConverterFactory.create(JsonUtils.getGson()))
- 然后看看GsonConverterFactory.creat()方法源码
- 使用{@code gson}创建一个实例以进行转换。编码到JSON并从JSON解码(当没有由头指定字符集时)将使用UTF-8。
- 创建了一个含有Gson对象实例的GsonConverterFactory,并返回给addConverterFactory()
public static GsonConverterFactory create(Gson gson) {if (gson == null) throw new NullPointerException("gson == null"); return new GsonConverterFactory(gson); }
2.4 addCallAdapterFactory(RxJava2CallAdapterFactory.create())源码分析
- 添加一个调用适配器工厂,用于支持服务方法返回类型
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {callAdapterFactories.add(checkNotNull(factory, "factory == null")); return this; }
- CallAdapterFactory:注意Factory生产的是CallAdapter,那么CallAdapter又是什么呢?
- 可以看到CallAdapter源代码如下所示,它是一个接口。主要作用是:将响应类型{@代码R}的{@链接调用}改编为{@代码T}的类型。实例由{@LinkplanFactory(一个工厂)创建,该工厂}是{@Link平原Retrofit.Builder#addCallAdapterFactory(Factory)已安装}到{@LinkRetroflit}实例中。
- 网络请求执行器(Call)的适配器,并且在Retrofit中提供了三种CallAdapterFactory: ExecutorCallAdapterFactory(默认)、DefaultCallAdapterFactory、RxJava2CallAdapterFactory
public interface CallAdapter<R, T> { Type responseType();T adapt(Call<R> call);abstract class Factory {public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,Retrofit retrofit);protected static Type getParameterUpperBound(int index, ParameterizedType type) {return Utils.getParameterUpperBound(index, type);}protected static Class<?> getRawType(Type type) {return Utils.getRawType(type);}}
}
- 接着,有伙伴可能会问它的作用是什么呢?
- 将默认的网络请求执行器(OkHttpCall)转换成适合被不同平台来调用的网络请求执行器形式
- 一开始Retrofit只打算利用OkHttpCall通过ExecutorCallbackCall切换线程;但后来发现使用Rxjava更加方便(不需要Handler来切换线程)。想要实现Rxjava的情况,那就得使用RxJavaCallAdapterFactoryCallAdapter将OkHttpCall转换成Rxjava(Scheduler)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
2.5 client(okHttpClient)源码分析
- 用于请求的HTTP客户端
- 指定用于创建{@link Call}实例的自定义调用工厂。
public Builder client(OkHttpClient client) {return callFactory(checkNotNull(client, "client == null"));
}public Builder callFactory(okhttp3.Call.Factory factory) {this.callFactory = checkNotNull(factory, "factory == null"); return this; }
2.6 Retrofit对象调用build()源码解析
- 看看源码
- 大概的流程就是创建适配器的防御性副本,并添加默认调用适配器。然后复制转换器的防御性副本,在然后添加内置的转化工厂.这可以防止重写其行为,但也可以确保在使用消耗所有类型的转换器时的正确行为。
- 通过前面步骤设置的变量,将Retrofit类的所有成员变量都配置完毕。就成功创建了对象!
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(); }
- 然后看看Retrofit的构造方法
- 成功建立一个Retrofit对象的标准:配置好Retrofit类里的成员变量,即配置好:
- serviceMethod:包含所有网络请求信息的对象
- baseUrl:网络请求的url地址
- callFactory:网络请求工厂
- adapterFactories:网络请求适配器工厂的集合
- converterFactories:数据转换器工厂的集合
- callbackExecutor:回调方法执行器
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,@Nullable Executor callbackExecutor, boolean validateEagerly) {this.callFactory = callFactory;this.baseUrl = baseUrl;this.converterFactories = converterFactories;
- 然后总结一下创建的过程
- 平台类型对象(Platform - Android)
- 网络请求的url地址(baseUrl)
- 网络请求工厂(callFactory) 默认使用OkHttpCall
- 网络请求适配器工厂的集合(adapterFactories) 本质是配置了网络请求适配器工厂- 默认是ExecutorCallAdapterFactory
- 数据转换器工厂的集合(converterFactories) 本质是配置了数据转换器工厂
- 回调方法执行器(callbackExecutor) 默认回调方法执行器作用是:切换线程(子线程 - 主线程)
3.创建ServiceMethod流程源码分析
3.1 首先看看请求网络代码过程
3.2 分析create(final Class<T> service)源码
- 源代码如下所示,这段代码很重要。
- 创建接口定义的API端点的实现。给定方法的相对路径是从描述请求类型的方法的注释中获得的。
- 先对service类进行判断是否是接口。这个时候你就知道为何只能定义service为接口呢……
- 接着就创建了ServiceMethod对象,并且把这个对象以键的形式存储到ConcurrentHashMap集合中
- 最后创建了网络请求接口的动态代理对象,通过代理模式中的动态代理模式,动态生成网络请求接口的代理类,并将代理类的实例创建交给InvocationHandler类 作为具体的实现,并最终返回一个动态代理对象。
- service.getClassLoader()作用是动态生成接口的实现类
- new Class<?>[] { service }作用是动态创建实例
- new InvocationHandler()作用是将代理类的实现交给 InvocationHandler类作为具体的实现
- 即通过动态生成的代理类,调用interfaces接口的方法实际上是通过调用InvocationHandler对象的invoke方法来完成指定的功能
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, @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<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); //根据配置好的serviceMethod对象创建okHttpCall对象 OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); //调用OkHttp,并根据okHttpCall返回rejava的Observe对象或者返回Call return serviceMethod.adapt(okHttpCall); } }); }
- 接着看一下validateServiceInterface方法操作了什么?
- 通过这个方法可知,如果service类不是接口则会抛异常。同时需要注意API接口不能扩展其他接口
static <T> void validateServiceInterface(Class<T> service) { if (!service.isInterface()) { throw new IllegalArgumentException("API declarations must be interfaces."); }
- 接着看看eagerlyValidateMethods这个方法的源码
- 判断是否需要提前验证,主要是给接口中每个方法的注解进行解析并得到一个ServiceMethod对象,然后以Method为键将该对象存入serviceMethodCache集合中。该集合是一个ConcurrentHashMap集合。
- 关于ConcurrentHashMap集合的源码分析,可以参考我的这篇博客ConcurrentHashMap
private void eagerlyValidateMethods(Class<?> service) {Platform platform = Platform.get();for (Method method : service.getDeclaredMethods()) { if (!platform.isDefaultMethod(method)) { loadServiceMethod(method); } } } 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(); serviceMethodCache.put(method, result); } } return result; }
- 知道return (T) roxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler invocationHandler)通过代理模式中的动态代理模式,在面试中也经常会问到该模式,那么该模式有什么特点呢?
- 当NetService对象调用getCall()接口中方法时会进行拦截,调用都会集中转发到 InvocationHandler#invoke (),可集中进行处理
- 获得网络请求接口实例上的所有注解
- 接着看看loadServiceMethod(Method method)方法源码
- 可以看到先从serviceMethodCache集合中获取result对象,然后对result进行非空判断
- 并且通过synchronized关键字设置了线程同步锁,创建ServiceMethod对象前,先看serviceMethodCache有没有缓存之前创建过的网络请求实例,若没缓存,则通过建造者模式创建 serviceMethod 对象。创建实例的缓存机制:采用单例模式从而实现一个 ServiceMethod 对象对应于网络请求接口里的一个方法
- 针对synchronized关键字的作用可以参考我的这篇博客:https://blog.csdn.net/m0_37700275/article/details/83151850
- 针对单利设计模式总结笔记:https://blog.csdn.net/m0_37700275/article/details/78276558

3.3 serviceMethod对象的创建过程
- 创建之前,首先会尝试根据方法从一个缓存列表中取出ServiceMethod实例,如果没有,在锁保护之后,还有再尝试一次,还是没有的情况下,才会去创建ServiceMethod。
- 第一步,先看看ServiceMethod的Builder方法
- 除了传递了两个参数外,还获取网络请求接口方法里的注释,获取网络请求接口方法里的参数类型,获取网络请求接口方法里的注解内容
Builder(Retrofit retrofit, Method method) {this.retrofit = retrofit;this.method = method;this.methodAnnotations = method.getAnnotations();this.parameterTypes = method.getGenericParameterTypes();this.parameterAnnotationsArray = method.getParameterAnnotations(); }
- 第二步,然后看看ServiceMethod的build()方法
- 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求适配器callAdapter对象
- 网络请求接口方法的返回值和注解类型,从Retrofit对象中获取该网络适配器返回的数据类型responseType
- 然后对responseType类型进行判断,如果是Response类型或者okhttp3.Response类型,则抛出异常
- 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的数据转换器responseConverter对象
- 然后采用for循环解析网络请求接口中方法的注解,注解包括:DELETE、GET、POST、HEAD、PATCH、PUT、OPTIONS、HTT等等
- 如果httpMethod为null。则抛出异常
public ServiceMethod build() {callAdapter = createCallAdapter();responseType = callAdapter.responseType();if (responseType == Response.class || responseType == okhttp3.Response.class) { throw methodError("'" + Utils.getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?"); } responseConverter = createResponseConverter(); for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } if (httpMethod == null) { throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.)."); } if (!hasBody) { if (isMultipart) { throw methodError( "Multipart can only be specified on HTTP methods with request body (e.g., @POST)."); } if (isFormEncoded) { throw methodError("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; p < parameterCount; p++) { Type parameterType = parameterTypes[p]; if (Utils.hasUnresolvableType(parameterType)) { throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s", parameterType); } Annotation[] parameterAnnotations = parameterAnnotationsArray[p]; if (parameterAnnotations == null) { throw parameterError(p, "No Retrofit annotation found."); } parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations); } if (relativeUrl == null && !gotUrl) { throw methodError("Missing either @%s URL or @Url parameter.", httpMethod); } if (!isFormEncoded && !isMultipart && !hasBody && gotBody) { throw methodError("Non-body HTTP method cannot contain @Body."); } if (isFormEncoded && !gotField) { throw methodError("Form-encoded method must contain at least one @Field."); } if (isMultipart && !gotPart) { throw methodError("Multipart method must contain at least one @Part."); } return new ServiceMethod<>(this); }
- 第三步,看看ServiceMethod(Builder<R, T> builder) 构造方法
ServiceMethod(Builder<R, T> builder) {this.callFactory = builder.retrofit.callFactory();this.callAdapter = builder.callAdapter;this.baseUrl = builder.retrofit.baseUrl();this.responseConverter = builder.responseConverter;this.httpMethod = builder.httpMethod; this.relativeUrl = builder.relativeUrl; this.headers = builder.headers; this.contentType = builder.contentType; this.hasBody = builder.hasBody; this.isFormEncoded = builder.isFormEncoded; this.isMultipart = builder.isMultipart; this.parameterHandlers = builder.parameterHandlers; }
4.注解的解析
4.1 callAdapter的创建源码分析
- 首先获取method的对象表示的方法的形式类型。然后获取method的注解。重点看看retrofit.callAdapter(returnType, annotations)主要做了什么?
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 {
- 看看retrofit.callAdapter(returnType, annotations)源码
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {return nextCallAdapter(null, returnType, annotations);
}public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,Annotation[] annotations) {
checkNotNull(returnType, "returnType == null"); checkNotNull(annotations, "annotations == null"); int start = callAdapterFactories.indexOf(skipPast) + 1; for (int i = start, count = callAdapterFactories.size(); i < count; i++) { CallAdapter<?, ?> adapter = callAdapterFactories.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(callAdapterFactories.get(i).getClass().getName()); } builder.append('\n'); } builder.append(" Tried:"); for (int i = start, count = callAdapterFactories.size(); i < count; i++) { builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName()); } throw new IllegalArgumentException(builder.toString()); }
4.2 responseConverter的创建源码分析
5.OkHttpCall的创建源码分析
5.1 new OkHttpCall<>(serviceMethod, args)源码分析
- 可以看到创建OkHttpCall对象需要两个参数,参数分别是配置好的ServiceMethod对象和输入的请求参数
final class OkHttpCall<T> implements Call<T> { private final ServiceMethod<T, ?> serviceMethod; private final @Nullable Object[] args; OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
- 接着看看return serviceMethod.adapt(okHttpCall)源码分析
- 创建的OkHttpCall对象传给第一步创建的serviceMethod对象中对应的网络请求适配器工厂的adapt()
- 返回对象类型:Android默认的是Call<>;若设置了RxJavaCallAdapterFactory,返回的则是Observable<>。如果这个地方不理解,可以继续往下看
T adapt(Call<R> call) {return callAdapter.adapt(call)
- 接着看看实际的调用
- ApiService对象实际上是动态代理对象Proxy.newProxyInstance(),并不是真正的网络请求接口创建的对象
- 当ApiService对象调用isUserOld()时会被动态代理对象Proxy.newProxyInstance()拦截,然后调用自身的InvocationHandler # invoke()
- invoke(Object proxy, Method method, Object... args)会传入3个参数:Object proxy:(代理对象)、Method method(调用的isUserOld()),Object... args(方法的参数,即getCall(*)中的)
- 接下来利用Java反射获取到isUserOld()的注解信息,配合args参数创建ServiceMethod对象。
- 最终创建并返回一个OkHttpCall类型的Call对象或者Observable
- OkHttpCall类是OkHttp的包装类
- 创建了OkHttpCall类型的Call对象还不能发送网络请求,需要创建Request对象【也就是异步请求方法】才能发送网络请求
ApiService apiService = retrofit.create(ApiService.class);
6.OkHttpCall的网络请求
6.1 OkHttpCall.execute()同步请求
6.2 OkHttpCall.enqueue()异步请求
- 关于异步操作封装库,可以看我的开源线程池封装库:https://github.com/yangchong211/YCThreadPool
- 如何调用可以看前面的代码介绍。这里就不介绍呢!
- 首先添加一个synchronized同步锁。创建OkHttp的Request对象,然后发送网络请求,然后解析返回数据。在这里,可能会想到,究竟是如何做到异步操作的呢?
@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) { 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<T> response; try { response = parseResponse(rawResponse); } catch (Throwable e) { callFailure(e); return; } try { callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { t.printStackTrace(); } } @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) { t.printStackTrace(); } } }); } private okhttp3.Call createRawCall() throws IOException { okhttp3.Call call = serviceMethod.toCall(args); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; }
- 从上可以知道,call操作异步,那么这个call是什么呢?那么我们看一下ExecutorCallAdapterFactory这个类,关于CallAdapterFactory是做什么用的?前面已经介绍呢!
- 如果你对异步线程还不是很熟悉,可以参考我的线程池封装库,里面已经很详细实现了异步线程操作,参考链接:https://github.com/yangchong211/YCThreadPool
- 线程切换,即将子线程切换到主线程,从而在主线程对返回的数据结果进行处理
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()) {
6.3 parseResponse解析网络数据源码解析
关于其他内容介绍
01.关于博客汇总链接
- 1.技术博客汇总
- 2.开源项目汇总
- 3.生活博客汇总
- 4.喜马拉雅音频汇总
- 5.其他汇总
02.关于我的博客
- 我的个人站点:www.yczbj.org,www.ycbjie.cn
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yang-chong-69-24/pins/posts
- 简书:http://www.jianshu.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
- 开源中国:https://my.oschina.net/zbj1618/blog
- 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 邮箱:yangchong211@163.com
- 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
转载于:https://www.cnblogs.com/yc211/p/9869857.html