Retrofit 是 Square 公司开发的网络请求框架,它是类型安全的,可用于 Android 和 Java 开发。通过注解的方式传递参数和 Java 动态代理,很大程度长简化了模版代码。
源码基于 com.squareup.retrofit2:retrofit:2.9.0。
简介
Builder 模式构建;
动态代理;
自定义注解;
默认只能将响应体转换为 OkHttp 中的 ResponseBody。
Retrofit 只负责生产能做网络请求的工作对象,他有点像一个工厂,只提供产品,工厂本身不处理网络请求,产品才能处理网络请求。
基本使用 1 2 3 4 public interface GitHubService { @GET("/users/{user}") Call<GitHubUser> getUser (@Path("user") String user) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Retrofit retrofit = new Retrofit .Builder() .baseUrl("https://api.github.com/" ) .addConverterFactory(GsonConverterFactory.create()) .build(); GitHubService service = retrofit.create(GitHubService.class);Call<GitHubUser> userCall = service.getUser("square" ); userCall.enqueue(new Callback <GitHubUser>() { @Override public void onResponse (Call<GitHubUser> call, Response<GitHubUser> response) { GitHubUser user = response.body(); } @Override public void onFailure (Call<GitHubUser> call, Throwable t) { } });
源码分析 Retrofit 整体流程如下:
1. 构造 Retrofit 对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public static final class Builder { Builder(Platform platform) { this .platform = platform; } public Builder () { this (Platform.get()); } 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(); } List<CallAdapter.Factory> callAdapterFactories = new ArrayList <>(this .callAdapterFactories); callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor)); List<Converter.Factory> converterFactories = new ArrayList <>(1 + this .converterFactories.size() + platform.defaultConverterFactoriesSize()); converterFactories.add(new BuiltInConverters ()); converterFactories.addAll(this .converterFactories); converterFactories.addAll(platform.defaultConverterFactories()); return new Retrofit ( callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); } }
url 不能为空;
callFactory 默认为 OkHttpClient;
支持 Java 和 Android 平台。
1 2 3 4 5 6 private static Platform findPlatform () { return "Dalvik" .equals(System.getProperty("java.vm.name" )) ? new Android () : new Platform (true ); }
2. 创建服务接口对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 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 Object invoke (Object proxy, Method method, Object[] args) throws Throwable { 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); } }); } private void validateServiceInterface (Class<?> service) { if (!service.isInterface()) { throw new IllegalArgumentException ("API declarations must be interfaces." ); } Deque<Class<?>> check = new ArrayDeque <>(1 ); check.add(service); while (!check.isEmpty()) { Class<?> candidate = check.removeFirst(); if (candidate.getTypeParameters().length != 0 ) { throw new IllegalArgumentException (message.toString()); } 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); } } } }
服务类必须是接口,且不支持泛型;
判断是否预加载服务方法;
通过动态代理
实例化服务接口对象。
3. 加载服务方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 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; }
服务方法存在,直接返回;
服务方法不存在,解析服务方法,并添加到缓存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 static <T> ServiceMethod<T> 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); }
根据注解解析出请求方法,请求地址和请求头等数据,并包装成 RequestFactory;
服务方法返回类型不能是 void,类型变量和通配符类型;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 static RequestFactory parseAnnotations (Retrofit retrofit, Method method) { return new Builder (retrofit, method).build(); } RequestFactory build () { for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } 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); } return new RequestFactory (this ); } private void parseMethodAnnotation (Annotation annotation) { if (annotation instanceof GET) { parseHttpMethodAndPath("GET" , ((GET) annotation).value(), false ); } else if (annotation instanceof POST) { parseHttpMethodAndPath("POST" , ((POST) annotation).value(), true ); } else if (annotation instanceof HTTP) { HTTP http = (HTTP) annotation; parseHttpMethodAndPath(http.method(), http.path(), http.hasBody()); } else if (annotation instanceof retrofit2.http.Headers) { headers = parseHeaders(headersToParse); } else if (annotation instanceof Multipart) { isMultipart = true ; } else if (annotation instanceof FormUrlEncoded) { isFormEncoded = true ; } } private void parseHttpMethodAndPath (String httpMethod, String value, boolean hasBody) { this .httpMethod = httpMethod; this .hasBody = hasBody; if (value.isEmpty()) { return ; } int question = value.indexOf('?' ); if (question != -1 && question < value.length() - 1 ) { String queryParams = value.substring(question + 1 ); Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams); if (queryParamMatcher.find()) { throw methodError( method, "URL query string \"%s\" must not have replace block. " + "For dynamic query parameters use @Query." , queryParams); } } this .relativeUrl = value; this .relativeUrlParamNames = parsePathParameters(value); }
构造器模式创建 requestFactory;
解析方法上的注解,获取 URL、请求方法、请求头等信息;
参数合法性检查;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations ( Retrofit retrofit, Method method, RequestFactory requestFactory) { Annotation[] annotations = method.getAnnotations(); Type adapterType; if (isKotlinSuspendFunction) { } else { adapterType = method.getGenericReturnType(); } CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations); Type responseType = callAdapter.responseType(); Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); okhttp3.Call.Factory callFactory = retrofit.callFactory; if (!isKotlinSuspendFunction) { return new CallAdapted <>(requestFactory, callFactory, responseConverter, callAdapter); } else if (continuationWantsResponse) { } else { } }
查找能处理此返回类型的 CallAdapter,默认是 DefaultCallAdapterFactory;
查找能处理此返回类型的 ConverterFactory。默认是 BuiltInConverters,只能处理 okhttp3.ResponseBody 和 Void 类型;
返回 HttpServiceMethod 的实现类 CallAdapted 对象。
4. 通过服务方法发起网络请求 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 abstract class HttpServiceMethod <ResponseT, ReturnT> extends ServiceMethod <ReturnT> { @Override final ReturnT invoke (Object[] args) { Call<ResponseT> call = new OkHttpCall <>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); } protected abstract ReturnT adapt (Call<ResponseT> call, Object[] args) ; static final class CallAdapted <ResponseT, ReturnT> extends HttpServiceMethod <ResponseT, ReturnT> { private final CallAdapter<ResponseT, ReturnT> callAdapter; @Override protected ReturnT adapt (Call<ResponseT> call, Object[] args) { return callAdapter.adapt(call); } } } final class DefaultCallAdapterFactory extends CallAdapter .Factory { @Override public 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); } }; } static final class ExecutorCallbackCall <T> implements Call <T> { @Override public void enqueue (final Callback<T> callback) { delegate.enqueue( new Callback <T>() { @Override public void onResponse (Call<T> call, final Response<T> response) { callbackExecutor.execute( () -> { if (delegate.isCanceled()) { 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)); } }); } @Override public Response<T> execute () throws IOException { return delegate.execute(); } } }
适配成 retrofit2.Call<GithubUser>、Single<GitHubUser>等;
通过 retrofit2.OkHttpCall 发起 http 请求;
响应消息回调。
注解 Query & QueryMap 用户设置 URL 中的参数。
1 2 3 @GET("/") Call<ResponseBody> list (@Query("page") int page) ; Call<ResponseBody> list (@QueryMap Map<String, String> params) ;
Field & FieldMap 用来设置 POST 请求的表单。
1 2 3 @FormUrlEncoded @POST("/") Call<ResponseBody> submit (@Field("name") ) ; Call<ResponseBody> submit (@FieldMap Map<String, String> params) ;
Part & PartMap 用来上传文件。
1 2 @Multipart @POST("upload") Call<ResponseBody> upload (@Part("description") RequestBody description, @Part MultipartBody.Part file) ;
请求适配器 CallAdapter<R, T> 负责把 Retrofit 中执行网络请求的 Call 对象,转换为接口中定义的 Call 对象(eg:okhttp3.Call< User >,Observable< User >,Flowable< User >)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public interface CallAdapter <R, T> { Type responseType () ; T adapt (Call<R> call) ; abstract class Factory { public abstract 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); } } }
Retrofit 默认实现了两个 CallAdapter:
DefaultCallAdapterFactory;
CompletableFutureCallAdapterFactory;
RxJava2CallAdapterFactory:
“com.squareup.retrofit2:adapter-rxjava2:2.9.0”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 public final class RxJava2CallAdapterFactory extends CallAdapter .Factory { @Override public @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { Class<?> rawType = getRawType(returnType); if (rawType == Completable.class) { return new RxJava2CallAdapter (Void.class, scheduler, isAsync, false , true , false , false , false , true ); } boolean isFlowable = rawType == Flowable.class; boolean isSingle = rawType == Single.class; boolean isMaybe = rawType == Maybe.class; if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) { return null ; } boolean isResult = false ; boolean isBody = false ; Type responseType; if (!(returnType instanceof ParameterizedType)) { throw new IllegalStateException ( name + " return type must be parameterized" + " as " + name + "<Foo> or " + name + "<? extends Foo>" ); } Type observableType = getParameterUpperBound(0 , (ParameterizedType) returnType); Class<?> rawObservableType = getRawType(observableType); if (rawObservableType == Response.class) { if (!(observableType instanceof ParameterizedType)) { throw new IllegalStateException ("Response must be parameterized" + " as Response<Foo> or Response<? extends Foo>" ); } responseType = getParameterUpperBound(0 , (ParameterizedType) observableType); } else if (rawObservableType == Result.class) { if (!(observableType instanceof ParameterizedType)) { throw new IllegalStateException ( "Result must be parameterized" + " as Result<Foo> or Result<? extends Foo>" ); } responseType = getParameterUpperBound(0 , (ParameterizedType) observableType); isResult = true ; } else { responseType = observableType; isBody = true ; } return new RxJava2CallAdapter (responseType, scheduler, isAsync, isResult, isBody, isFlowable, isSingle, isMaybe, false ); } } final class RxJava2CallAdapter <R> implements CallAdapter <R, Object> { @Override public Type responseType () { return responseType; } }
转换器 Converter<F, T>
扩展传递参数,如传递 File 类型;
转换响应数据,如 JSON、XML、二进制等格式(由 ResponseBody 封装)转化为 T 类型的对象。
Retrofit 在选择合适的 Converter 时,主要依赖于需要转换的对象类型。在添加 Converter 时,注意 Converter 支持的类型的包含关系以及其顺序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public interface Converter <F, T> { T convert (F value) throws IOException; abstract class Factory { public Converter<ResponseBody, ?> responseBodyConverter( Type type, Annotation[] annotations, Retrofit retrofit) { return null ; } public Converter<?, RequestBody> requestBodyConverter( Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { return null ; } public Converter<?, String> stringConverter( Type type, Annotation[] annotations, Retrofit retrofit) { return null ; } protected static Type getParameterUpperBound (int index, ParameterizedType type) { return Utils.getParameterUpperBound(index, type); } protected static Class<?> getRawType(Type type) { return Utils.getRawType(type); } } }
Converter.Factory 的默认实现类有 BuiltInConverters
和 OptionalConverterFactory
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 final class BuiltInConverters extends Converter .Factory { @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { if (type == ResponseBody.class) { return Utils.isAnnotationPresent(annotations, Streaming.class) ? StreamingResponseBodyConverter.INSTANCE : BufferingResponseBodyConverter.INSTANCE; } if (type == Void.class) { return VoidResponseBodyConverter.INSTANCE; } if (checkForKotlinUnit) { if (type == Unit.class) { return UnitResponseBodyConverter.INSTANCE; } } return null ; } }
GsonConverterFactory:
“com.squareup.retrofit2:converter-gson:2.9.0”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 public final class GsonConverterFactory extends Converter .Factory { public static GsonConverterFactory create () { return create(new 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); } } 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()); } } 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(); } } }
自定义上传文件转换器:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class FileRequestBodyConverterFactory extends Converter .Factory { @Override public Converter<File, RequestBody> requestBodyConverter (Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { return new FileRequestBodyConverter (); } private static class FileRequestBodyConverter implements Converter <File, RequestBody> { @Override public RequestBody convert (File value) throws IOException { return RequestBody.create(MediaType.parse("application/otcet-stream" ), value); } } }
自定义响应转换器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class MyResponseBodyConverterFactory extends Converter .Factory { @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return new MyResponseBodyConverter (); } private static class MyResponseBodyConverter implements Converter <ResponseBody, Result> { @Override public Result convert (ResponseBody value) throws IOException { RawResult rawResult = new Gson ().fromJson(value.toString(), RawResult.class); return new Result (rawResult.err, rawResult.content, rawResult.message); } } private static class Result { private final int code; private final String content; private final String message; public Result (int code, String content, String message) { this .code = code; this .content = content; this .message = message; } } private static class RawResult { private int err; private String content; private String message; } }
ParameterHandler<T> 负责解析 API 定义时每个方法的参数,并在构造 HTTP 请求时设置参数。
OkHttpCall<T> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 final class OkHttpCall <T> implements Call <T> { @Override public void enqueue (final Callback<T> callback) { synchronized (this ) { if (executed) throw new IllegalStateException ("Already executed." ); executed = true ; call = rawCall; failure = creationFailure; if (call == null && failure == null ) { call = rawCall = createRawCall(); } } call.enqueue( new okhttp3 .Callback() { @Override public void onResponse (okhttp3.Call call, okhttp3.Response rawResponse) { Response<T> response = parseResponse(rawResponse); callback.onResponse(OkHttpCall.this , response); } }); } Response<T> parseResponse (okhttp3.Response rawResponse) throws IOException { ResponseBody rawBody = rawResponse.body(); rawResponse = rawResponse .newBuilder() .body(new NoContentResponseBody (rawBody.contentType(), rawBody.contentLength())) .build(); ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody (rawBody); T body = responseConverter.convert(catchingBody); return Response.success(body, rawResponse); } }
总结
使用构造器模式创建 retrofit,核心参数有 baseurl,callFactory,converterFactories,adapterFactories 和 excallbackExecutor;
通过动态地理实例化接口服务对象;
调用服务方法时,解析方法上的注解,构造 ServiceMethod 实例;
通过 CallAdapter 适配请求,获取 Call 对象,发起网络请求;
响应体 ResponseBody 通过 Converter 转换成具体类型的对象。
参考 [1] 从架构角度看 Retrofit 的作用、原理和启示 [2] 拆轮子系列:拆 Retrofit