Retrofit详解
已经有了okhttp,为什么还需要Retrofit:
- 自动转换数据格式:
- 您提到Retrofit提供了自动转换数据格式的功能,这是非常准确的。Retrofit可以与多种转换器(如Gson、Jackson、Moshi等)集成,自动将HTTP响应体转换为Java对象,同样也可以将Java对象转换为请求体。这大大简化了数据处理的代码,使得开发者无需手动解析JSON或构建请求体。
- 声明式的API:
- Retrofit确实提供了声明式的API,这是它的一大亮点。通过简单的接口定义,开发者可以轻松地描述HTTP请求(如GET、POST等)的URL、请求方法、请求头和请求体等。这种方式使得HTTP请求的配置更加直观和易于管理。
- 配合RxJava:
- 您提到Retrofit可以配合RxJava使用,这也是非常正确的。Retrofit 2.x版本开始支持RxJava 2.x,允许开发者以响应式编程的方式处理HTTP请求。通过RxJava,开发者可以更加灵活地处理异步操作、错误处理、数据转换等,使得代码更加简洁和可读。
1:用法:
Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(gson)) .baseUrl("https://api.github.com/") .build(); GithubService service = retrofit.create(GithubService.class); service.listRepos("woniupanpa").enqueue(new Callback<List<Repo>>() { @Override public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) { Log.d("yjm" ,"success" + gson.toJson(response.body())); System.out.println("yjm success"); } @Override public void onFailure(Call<List<Repo>> call, Throwable t) { } });
public interface GithubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); @GET("users/{user}/repos") Call<List<Repo>> getUser(@Path("user") String user); }
2:源码:
1)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); } }); }
解析:该方法采用动态代理的模式,所谓动态代理是这样的,举个例子:
代理类A和被代理类B,他们都继承自接口 C,并且A持有B的实例,这样,B里面的任何方法都要经过A的invoke执行,这样,A就能够实现对B的所有方法的统一监控,在Retrofit里面就类似这样:
接口:
public interface GithubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); @GET("users/{user}/repos") Call<List<Repo>> getUser(@Path("user") String user); }
被代理类:BService
public class BService implements GithubService{ @Override public Call<List<Repo>> listRepos(String user) { return null; } @Override public Call<List<Repo>> getUser(String user) { return null; } }
代理类A:
public class RealService implements GithubService{ InvocationHandler invocationHandler = new InvocationHandler() { @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); } }); @Override public Call<List<Repo>> listRepos(String user) { try { Method method = GithubService.class.getMethod("listRepos"); return (Call<List<Repo>>) invocationHandler.invoke(this, method, null); } catch (NoSuchMethodException e) { e.printStackTrace(); }finally { return null; } } @Override public Call<List<Repo>> getUser(String user) { try { Method method = GithubService.class.getMethod("getUser"); return (Call<List<Repo>>) invocationHandler.invoke(this, method, null); } catch (NoSuchMethodException e) { e.printStackTrace(); }finally { return null; } } }
以上代码就实现了:被代理类ServiceB的所有方法都交给代理类RealService执行,即都会经过RealService的invoke()方法。
这样,代理类RealService就能更实现对被代理类BService 的所有方法的统一监控。
在Retrofit案例中,比较特殊的一点是,它不存在被代理类BService这个角色,它有的只是接口GithubService和代理类RealServce,
GithubService:
public interface GithubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
@GET("users/{user}/repos")
Call<List<Repo>> getUser(@Path("user") String user);
}
RealServce:RealService的实例就是:Proxy.newProxyInstance....
通过以上分析就能够得出以下结论:
GithubService service = retrofit.create(GithubService.class);
该代码得到的是一个GithubService这个接口对应的动态代理模式中的代理类RealService的实例
当应用层代码执行:service.listRepos("woniupanpa")的时候,就是把listRepos这个方法丢进RealService的invoke执行:
@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); }
所以这里面的methode,对应的是GithubService这个接口里面的方法,当应用层调用任意一个接口的时候,都会经过该方法。
我们在乎的是method方法里面定义的注解和参数,比如@Post, @Body,这些才是我们需要的东西,所以我们看到,在应用层,我们只需要去定义接口就可以,不必关心该类真正的实现,所以也不需要存在被代理类。
public interface GithubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
@GET("users/{user}/repos")
Call<List<Repo>> getUser(@Path("user") String user);
}
2)ServiceMethod
@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); }
看最后一行loadServiceMethod(method).invoke(args)->
ServiceMethod.parseAnnotations(this, method);->
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);->
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
parseAnnotations:
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:
Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; this.methodAnnotations = method.getAnnotations(); this.parameterTypes = method.getGenericParameterTypes(); this.parameterAnnotationsArray = method.getParameterAnnotations(); }
methodAnnotations是接口的注解,@GET("users/{user}/repos")
parameterTypes是参数:String user
parameterAnnotationsArray :是参数的注解@Path("user")
由此可知:loadServiceMethod(method).invoke(args)执行的是HttpServiceMethod的invoke:
@Override final @Nullable ReturnT invoke(Object[] args) { Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); }
3)HttpServiceMethod:
@Override final @Nullable ReturnT invoke(Object[] args) { Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); }
CallAdapted继承HttpServiceMethod,所以执行CallAdapted的adapt:
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) { return callAdapter.adapt(call); }
往回翻会发现,callAdapter来自HttpServiceMethod的parseAnnotations:
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
if (!isKotlinSuspendFunction) { return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
到此为止,先总结一下:
loadServiceMethod(method).invoke(args)执行的是:
CallAdapted的invoke,因为CallAdapted继承自HttpServiceMethod,即HttpServiceMethod的invoke()方法。
继续往下:
createCallAdapter:
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的nextCallAdapter:
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; } }
由此可知,CallAdapter的实例来自callAdapterFactories,再看看callAdapterFactories来自哪里:
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; // Copy+unmodifiable at call site. this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site. this.callbackExecutor = callbackExecutor; this.validateEagerly = validateEagerly; }
往上找最终会发现,来自应用层代码:
Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .baseUrl("https://api.github.com/") .build();
如果用户层没有添加addCallAdapterFactory,那么他还有有一个默认的defaultCallAdapterFactories:
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
假设我们这时候没有添加,那么总结一下:loadServiceMethod(method).invoke(args)执行的是HttpServiceMethod的invoke:
DefultCallAdapterFactory里面的CallAdapter的adapt():
@Override public Call<Object> adapt(Call<Object> call) { return executor == null ? call : new ExecutorCallbackCall<>(executor, call); }
这里的call来自HttpServiceMethod的,即是一个OkhttpCall
@Override final @Nullable ReturnT invoke(Object[] args) { Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); }
再回到DefultCallAdapterFactory里面的CallAdapter的adapt():可知
最终执行的到OkhttpCall的enqueue,发起异步通讯。