Retrofit 是如何获取返回值 Call<T> 中的类型 T, 以提供给 Gson 使用的?

北城余情 提交于 2020-03-05 21:19:40

Call<T>的类型 T 即Response<T>的类型 T,获得了Call<T>就能够正确输出给Response<T>。那么Retrofit是怎么做到的呢?

以下是HttpServiceMethod<ResponseT, ReturnT>中的 static 方法:

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
										Retrofit retrofit, Method method, RequestFactory requestFactory) {
		// 省略部分代码
		// ...
		Type adapterType;
		// 解析 kotlin 语言中的返回值
		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<T>.
						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 {
				// 解析 java 语言写的返回值(写过的都知道,这个很容易懂了)
		  		adapterType = method.getGenericReturnType();
		}
		// 省略部分代码
		// ...
}

拿到adapterType之后,又辗转调用了CallAdapter.Factory. get()以创建实现了CallAdapter接口的CallAdapter

public interface CallAdapter<R, T> {
		// 省略部分代码
		// ...
		abstract class Factory {
 				public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit);
				// ...
		}
}

注意前面的adapterTypeCall<T>,所以要取出里面的T,才是真正要传给 Gson 从而输出的类型:

// 这是 CallAdapter.Factory. get() 的 impl
@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);
		// ...
		// 在这里 CallAdapter 接口的实现
		return new CallAdapter<Object, Call<?>>() {
				@Override public Type responseType() {
						return responseType;
				}
				// ...
		};
}

Call<T>有类似 GsonTypeToken的功能,如:

@KeepV
data class Data<T>(val users: List<T>)
data class User(val id: Long)

interface AaaService {
		@GET("a/b/c.json")
		fun getAbc(): Call<Data<User>>
}

能够正确解析出Data<User>,相当于new TypeToken<Data<User>>{}.getType(),所以能传给 Gson 从而 输入正确的Response<Data<User>>。细节就不多讲了,这里主要是做个笔记备忘。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!