1.简单运用
// 接口署理类
interface WanAndroidApi {
@GET("xxx/xx/xxx")
fun getHomeList(
@Path("page") page: Int
): Call<BaseBean<HomeDataBean?>?>?
}
// 制作retrofit目标,设置Gson转化工厂
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
// 创立接口目标
service = retrofit.create(WanAndroidApi::class.java)
// 异步恳求
service.getHomeList().enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
handler.obtainMessage(successId, response.body()).sendToTarget()
}
override fun onFailure(call: Call<T>, t: Throwable) {
val throwable = HandlerException.handleException(t)
handler.obtainMessage(errorid, throwable.message).sendToTarget()
}
})
上面便是简单的运用了,制作retrofit目标,设置Gson转化仓库,创立接口实例,恳求网络。
2. Retrofit.create办法
public <T> T create(final Class<T> service) {
// 榜首步 验证接口服务
validateServiceInterface(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);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
可以把这个办法的行为分为这两步,1、验证接口 2、回来动态署理类。什么是动态署理,动态署理便是在代码运行的时分去生成的类,而不是编译的时分。这被称为动态
2.1 Retrofit.validateServiceInterface办法
private void validateServiceInterface(Class<?> service) {
// 榜首块 假如传过来的class类不是interface则抛反常
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// 第二块 父类或本身类存在范型则抛出反常 如(interface lala<T>{....})
Deque<Class<?>> check = new ArrayDeque<>(1);
check.add(service);
while (!check.isEmpty()) {
Class<?> candidate = check.removeFirst();
if (candidate.getTypeParameters().length != 0) {
StringBuilder message =
new StringBuilder("Type parameters are unsupported on ").append(candidate.getName());
if (candidate != service) {
message.append(" which is an interface of ").append(service.getName());
}
throw new IllegalArgumentException(message.toString());
}
// 将传进来的类的父类放入行列中,假如不太懂可以看看getInterfaces办法
Collections.addAll(check, candidate.getInterfaces());
}
// 调试运用 将类中的一切办法加载出来
if (validateEagerly) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
}
这儿有做两个抛出反常的判别,1、类是否为interface 2、是否类上有范型(如(interface lala<T>{….}))3、加载一切办法,这个为调试运用,默许为false,如有需要可以在结构Retrofit时设置validateEagerly办法。
小结:到这create办法就走完了,无非是判别传过来的类是否合规,然后回来动态署理类
3 回到动态署理中的代码 — 怎么加载办法的呢
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.
// 假如办法归于object中的办法。直接调用。例如toString等等都办法
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
// 这儿验证一些默许办法之类的,这种特性在java8以上才有
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
当咱们调用service.getHomeList()时就会,抵达invocationHandler中的invoke办法。这儿面的一些判别都写了注释不赘述了,持续往loadServiceMethod办法看
3.1 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) {
// 解析注解来回来对应的method目标
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
这儿的代码看下来,先从一个map中拿,拿到了就直接回来。没拿到就解析获取,获取后存入缓存中。那要害的代码便是解析获取那一行了。提一下:留意这儿回来的是ServiceMethod目标,它内部有invoke办法
3.1.1 Retrofit.parseAnnotations办法
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 1
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
// 2 这一块 是做办法回来类型合规判别
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.");
}
// 3
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
这儿有两点比较古怪,便是1和3,都是parseAnnotations办法,只不过是不同的类中的办法。详细是做什么的,先看榜首个
3.1.1.1 RequestFactory.parseAnnotations办法
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);
}
// 这下边做了许多合规性的判别,比方说:是否存在恳求办法的注解
...
return new RequestFactory(this);
}
private void parseMethodAnnotation(Annotation annotation) {
// 这底下便是依据范型的类型。来对应的去采取相应解析战略
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError(method, "@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
这样就知道都做了啥了,首先这又是制作者形式,在结构办法中就直接去获取办法中的一切注解然后遍历的去解析对应的注解,解析完注解之后,在对办法进行合规性判别,当然这个代码许多,有兴趣可以自行查阅。这儿也可以看出来retrofit支撑许多的恳求办法delete、patch和put等等都支撑
小结:解析是依据获取办法中的一切注解,然后遍历办法的一切注解,然后对每个注解有相应的解析战略。其中还做了许多合规性判别,恳求参数和注解恳求办法等等。
4 回到3.1.1 的第三点
4.1 回来call目标
都知道retrofit是对okhttp的封装,那怎么调用到okhttp的call呢?
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
// 做了一些kt挂起办法的判别。这儿省掉了
if (isKotlinSuspendFunction) {
......
} else {
adapterType = method.getGenericReturnType();
}
// 创立call适配器
CallAdapter<ResponseT, ReturnT> 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<String>)");
}
// 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<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
// 回来了Call适配器
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
......
} else {
......
}
}
从retrofit稍微高一点的版别之后,开端支撑kotlin的挂起办法,我这边就把相关的代码省掉了,有兴趣可以自己扒一下。留意这儿有创立一个呼应后的呼应转化器responseConverter,后面传给了Call目标,默许状况isKotlinSuspendFunction是false。这办法中所做的事情是回来callAdapted。这儿不由发出疑问,啥东西啊,之前要回来一个ServiceMethod,这儿回来一个callAdapted。都在干嘛啊,要绕晕了!不急,先整理一下这儿的类结构
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT>
}
这样就明晰了是不,callAdapted是ServiceMethod后辈类。那这儿就没啥回来类型上的疑问了,
但不懂为什么要走这么多层。咱们把思绪拉回到动态署理生成的代码中的这段代码
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
咱们加载办法是为了调用它的invoke办法啊,那上头是回来的是callAdapted类型,瞧瞧他的invoke办法
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}
他就潦草几句代码,并没有invoke办法啊!我哭死,由于承继关系,那咱们就去他的父类HttpServiceMethod中找吧!
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
功夫不负有心人,果然在他的父类中找到了相关办法,这儿实例化了一个一个OkHttpCall然后调用了他的本身adapt办法。这个时分咱们回看回看HttpServiceMethod.parseAnnotations办法就理解了这儿用子类的意义了,假如办法是kotlin的挂起办法,那么会回来其他的类,当然这个类也是承继HttpServiceMethod,他也完成了adapt办法。这就解说得通了,由于有不同战略所以运用的相应的自类来进行处理。这儿要留意,他传到adapt里的是OkHttpCall目标,后续会用到
看CallAdapted的adapt办法。
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
很简单,就一行代码,调用了callAdapter的adapt。持续往下看。
public interface CallAdapter<R, T> {
T adapt(Call<R> call);
}
亲娘诶,咋是一个interfeca勒。有得回来查看callAdapter是怎么创立出来的了。
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
在HttpServiceMethod.parseAnnotations办法中是这样创立的,持续挖createCallAdapter办法。下面就把接下去的代码调出的一切办法粘贴出来了
// HttpServiceMethod类的办法中
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
//noinspection unchecked
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, 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(
@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
Objects.requireNonNull(returnType, "returnType == null");
Objects.requireNonNull(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());
}
终究调用到了Retrofit类中的nextCallAdapter办法,但其实这个办法不用细看了,都是从一个调集中取,没取到就抛反常。所以应该关注这个调集是从哪里设置的。咱们点击这个callAdapterFactories参数会发现他在Retrofit的结构办法中才会被赋值,但制作者的运用,所以就在制作者的build办法中可以找到相关代码是
// Retrofit.Builder的build办法中
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// platform中的代码
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return hasJava8Types
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
// DefaultCallAdapterFactorie 中的get办法
@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<Foo> or Call<? extends Foo>");
}
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<Object> adapt(Call<Object> call) {
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
};
}
其中他的adapt办法会回来call目标,默许状况下executor不会为空,除非在注解中存在SkipCallbackExecutor的实例。假如executor为空就会回来上面的OkHttpCall目标,不然回来
ExecutorCallbackCall目标。可是call传入到了ExecutorCallbackCall中。
小结:到这儿从运用动态署理类里的办法到此就完毕了(例如运用代码中的service.getHomeList())。最后是回来了Call目标,默许回来的是ExecutorCallbackCall目标,但目前还没有调用到OKHttp的Call
4.2 call目标的enqueue办法
在获取到Call目标后,肯定是要进行网络恳求的。基于4.1的小结,call目标默许状况是ExecutorCallbackCall目标。咱们直接看他的enqueue办法即可。
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override
public void enqueue(final Callback<T> callback) {
Objects.requireNonNull(callback, "callback == null");
// 1.调用了OkHttpCall的enqueue办法
delegate.enqueue(
new Callback<T>() {
@Override
public void onResponse(Call<T> call, final Response<T> response) {
// 2.这儿运用了一个executor,线程切换了
callbackExecutor.execute(
() -> {
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) {
// 2.这儿运用了一个executor,线程切换了
callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
}
});
}
这儿不难看出delegate是OkHttpCall目标,因为在初始化ExecutorCallbackCall目标时传入了OkHttpCall。1、enqueue办法中调用了OKHttpCall的enqueue办法。2、在回调中切换了线程
4.2.1 OkHttpCall.enqueue —怎么调用到的OkHttp的Call
@Override
public void enqueue(final Callback<T> callback) {
Objects.requireNonNull(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 {
// 创立OkHttp的Call
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) {
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
}
}
});
}
private okhttp3.Call createRawCall() throws IOException {
// 这儿callFactory.newCall办法就跑到了okHttpClient的newCall办法
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
这儿就总算走到了OkHttp中的代码了,okhttp就不说了,上篇文章有说过
/post/723451…
但咱们还是看看OkHttpClient的newCall办法吧
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
这儿回来了OkHttp的RealCall目标,这样Retrofit就和okhttp串起来了
4.2.2 切换线程 —为什么说Retrofitd可以在回调中直接烘托ui
那为什么在retrofit的回调里可以切换线程呢?来看代码
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) {
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
}
}
});
在OkHttpCall类中调用OkHttp的Call的enqueue办法的回调中并没有切换线程,仅仅把相关数据处理放到Retrofit的回调中。之前说过Retrofit中的call是ExecutorCallbackCall目标,在他的回调中确实是有线程切换的啊!那这个线程是怎么切换到主线程的呢?
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override
public void enqueue(final Callback<T> callback) {
Objects.requireNonNull(callback, "callback == null");
delegate.enqueue(
new Callback<T>() {
@Override
public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(
() -> {
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(() -> callback.onFailure(ExecutorCallbackCall.this, t));
}
});
}
线程是从外面传过来的,所以又得回头去追寻代码。代码回倒这边就直接粘贴了
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
......
@Override
public Call<Object> adapt(Call<Object> call) {
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
......
}
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> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
代码往回倒就发现了这个线程是由platform.defaultCallbackExecutor()供给,稍微介绍一下Platform这个类他是一个平台类,他的实例办法
private static Platform findPlatform() {
return "Dalvik".equals(System.getProperty("java.vm.name"))
? new Android() //
: new Platform(true);
}
android的虚拟机是Dalvik所以用的是Android
static final class Android extends Platform {
Android() {
super(Build.VERSION.SDK_INT >= 24);
}
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Nullable
@Override
Object invokeDefaultMethod(
Method method, Class<?> declaringClass, Object object, Object... args) throws Throwable {
if (Build.VERSION.SDK_INT < 26) {
throw new UnsupportedOperationException(
"Calling default methods on API 24 and 25 is not supported");
}
return super.invokeDefaultMethod(method, declaringClass, object, args);
}
static final class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
}
啊!到这儿就知道他retrofit回调可以直接刷新ui到原因啦,是因为回调是在主线程,当然得谨慎一些,在OkHttpCall的回调中还是非主线程,到ExecutorCallbackCall到回调中时就切换到了主线程。切换线程的办法是经过handler。
5.自动转化json –怎么支撑自动转化的
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
增加一行代码addConverterFactory即可。
5.1 恳求转化
public final class GsonConverterFactory extends Converter.Factory {
public static GsonConverterFactory create() {
return create(new Gson());
}
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(
Type type,
Annotation[] parameterAnnotations,
Annotation[] methodAnnotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
看到了这个类里主要行为就有有一个gson成员,两个办法,一个办法供给呼应转化,一个供给恳求转化。
这边就快进了,恳求转化是在解析办法中的解析参数RequestFactory.parseParameter办法中
Converter<?, RequestBody> converter =
retrofit.requestBodyConverter(type, annotations, methodAnnotations);
return new ParameterHandler.Header<>(name, converter).iterable();
final ParameterHandler<Iterable<T>> iterable() {
return new ParameterHandler<Iterable<T>>() {
@Override
void apply(RequestBuilder builder, @Nullable Iterable<T> values) throws IOException {
if (values == null) return; // Skip null values.
for (T value : values) {
ParameterHandler.this.apply(builder, value);
}
}
};
}
static final class Header<T> extends ParameterHandler<T> {
private final String name;
private final Converter<T, String> valueConverter;
Header(String name, Converter<T, String> valueConverter) {
this.name = Objects.requireNonNull(name, "name == null");
this.valueConverter = valueConverter;
}
@Override
void apply(RequestBuilder builder, @Nullable T value) throws IOException {
if (value == null) return; // Skip null values.
// 这儿convert办法就进行了转化
String headerValue = valueConverter.convert(value);
if (headerValue == null) return; // Skip converted but null values.
builder.addHeader(name, headerValue);
}
}
解析办法中的解析参数是给每个param都大致存了对应的恳求转化器,上面举例的是header。到调用convert办法就去进行转化了,看看恳求转化里的代码。
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public RequestBody convert(T value) throws IOException {
// 转化代码
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
其中type办法是‘application/json’,需要留意
5.2 呼应转化
还记得上面要大家留意到传给call的呼应转化器嘛,在HttpServiceMethod.parseAnnotations办法中。
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
他的后续createResponseConverter这儿就不走了,跟callAdapted相似都是跑到了Retrofit里的结构器中。
转化器还被传到了Call目标中。在调用OkHttp的Call目标恳求的回调中呼应时触发转化。
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) {
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
}
}
});
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse =
rawResponse
.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
// 调用转化器
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
排除了其他的状况码,到最后转化。最后贴上呼应转化器代码
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}
确实精妙的代码。
小结:在解析办法中的解析参数时,会把对应的参数解析json,用于恳求。并且在加载办法时,把呼应转化器也设置给call了。当恳求回来时履行回调会触发转化呼应json。
当然个人还存在一个问题的,自始至终,内部全部运用的是范型,是怎么防止范型擦除机制的,特别是在呼应回来进行转化的时分。我目前个人只能全部归结到动态署理上,希望大佬们可以指点指点。